{
  "components": {
    "examples": {
      "forbidden": {
        "summary": "The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code.",
        "value": {
          "error": {
            "code": "forbidden",
            "message": "The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 403,
            "retryable": false,
            "param": null,
            "remediation": "Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "doc_url": "https://socialtap.dev/docs/errors/#forbidden",
            "details": {},
            "charged": false
          }
        }
      },
      "idempotency_key_in_progress": {
        "summary": "A request with this Idempotency-Key is still running.",
        "value": {
          "error": {
            "code": "idempotency_key_in_progress",
            "message": "A request with this Idempotency-Key is still running.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 409,
            "retryable": true,
            "param": null,
            "remediation": "Retry after the seconds in the retry-after header to get that request's result.",
            "doc_url": "https://socialtap.dev/docs/errors/#idempotency_key_in_progress",
            "details": {},
            "charged": false
          }
        }
      },
      "idempotency_key_reused": {
        "summary": "This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another.",
        "value": {
          "error": {
            "code": "idempotency_key_reused",
            "message": "This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 422,
            "retryable": false,
            "param": null,
            "remediation": "Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "doc_url": "https://socialtap.dev/docs/errors/#idempotency_key_reused",
            "details": {},
            "charged": false
          }
        }
      },
      "insufficient_credits": {
        "summary": "The account does not have enough credits for this request.",
        "value": {
          "error": {
            "code": "insufficient_credits",
            "message": "The account does not have enough credits for this request.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 402,
            "retryable": false,
            "param": null,
            "remediation": "Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.",
            "doc_url": "https://socialtap.dev/docs/errors/#insufficient_credits",
            "details": {},
            "charged": false
          }
        }
      },
      "internal": {
        "summary": "An unexpected error on SocialTap's side.",
        "value": {
          "error": {
            "code": "internal",
            "message": "An unexpected error on SocialTap's side.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 500,
            "retryable": true,
            "param": null,
            "remediation": "Retry with backoff. If it keeps happening, contact support with the request_id.",
            "doc_url": "https://socialtap.dev/docs/errors/#internal",
            "details": {},
            "charged": false
          }
        }
      },
      "invalid_cursor": {
        "summary": "The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it.",
        "value": {
          "error": {
            "code": "invalid_cursor",
            "message": "The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 400,
            "retryable": false,
            "param": null,
            "remediation": "Repeat the original request without cursor to start the list again.",
            "doc_url": "https://socialtap.dev/docs/errors/#invalid_cursor",
            "details": {},
            "charged": false
          }
        }
      },
      "invalid_input": {
        "summary": "A parameter is missing or malformed, or the link is not one this endpoint takes.",
        "value": {
          "error": {
            "code": "invalid_input",
            "message": "A parameter is missing or malformed, or the link is not one this endpoint takes.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 400,
            "retryable": false,
            "param": null,
            "remediation": "Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "doc_url": "https://socialtap.dev/docs/errors/#invalid_input",
            "details": {},
            "charged": false
          }
        }
      },
      "job_not_found": {
        "summary": "The account has no job with this ID: the ID is wrong, or the job is past its retention.",
        "value": {
          "error": {
            "code": "job_not_found",
            "message": "The account has no job with this ID: the ID is wrong, or the job is past its retention.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 404,
            "retryable": false,
            "param": null,
            "remediation": "Check the job ID. Finished jobs are kept for a limited time.",
            "doc_url": "https://socialtap.dev/docs/errors/#job_not_found",
            "details": {},
            "charged": false
          }
        }
      },
      "no_live": {
        "summary": "The account exists but has no live broadcast to show: nothing on air or scheduled, and no past broadcast the platform still shows.",
        "value": {
          "error": {
            "code": "no_live",
            "message": "The account exists but has no live broadcast to show: nothing on air or scheduled, and no past broadcast the platform still shows.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 404,
            "retryable": false,
            "param": null,
            "remediation": "Do not retry now. Ask again later, when the account may be live.",
            "doc_url": "https://socialtap.dev/docs/errors/#no_live",
            "details": {},
            "charged": false
          }
        }
      },
      "no_media": {
        "summary": "The post exists but has no file to download: a text or link post, or one whose media the platform does not serve logged out.",
        "value": {
          "error": {
            "code": "no_media",
            "message": "The post exists but has no file to download: a text or link post, or one whose media the platform does not serve logged out.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 404,
            "retryable": false,
            "param": null,
            "remediation": "Do not retry. Fetch the post itself for its text and links.",
            "doc_url": "https://socialtap.dev/docs/errors/#no_media",
            "details": {},
            "charged": false
          }
        }
      },
      "no_transcript": {
        "summary": "The video or audio exists but has no transcript: no caption track and no speech to transcribe.",
        "value": {
          "error": {
            "code": "no_transcript",
            "message": "The video or audio exists but has no transcript: no caption track and no speech to transcribe.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 404,
            "retryable": false,
            "param": null,
            "remediation": "Do not retry. If the platform offers other languages, try one with lang.",
            "doc_url": "https://socialtap.dev/docs/errors/#no_transcript",
            "details": {},
            "charged": false
          }
        }
      },
      "not_found": {
        "summary": "The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why).",
        "value": {
          "error": {
            "code": "not_found",
            "message": "The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why).",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 404,
            "retryable": false,
            "param": null,
            "remediation": "Check the link or ID. Do not retry.",
            "doc_url": "https://socialtap.dev/docs/errors/#not_found",
            "details": {},
            "charged": false
          }
        }
      },
      "overloaded": {
        "summary": "SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged.",
        "value": {
          "error": {
            "code": "overloaded",
            "message": "SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 503,
            "retryable": true,
            "param": null,
            "remediation": "Retry after the seconds in the retry-after header. Failed requests are free.",
            "doc_url": "https://socialtap.dev/docs/errors/#overloaded",
            "details": {},
            "charged": false
          }
        }
      },
      "private_or_unavailable": {
        "summary": "The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code.",
        "value": {
          "error": {
            "code": "private_or_unavailable",
            "message": "The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 403,
            "retryable": false,
            "param": null,
            "remediation": "Only public items can be fetched. Do not retry.",
            "doc_url": "https://socialtap.dev/docs/errors/#private_or_unavailable",
            "details": {},
            "charged": false
          }
        }
      },
      "rate_limited": {
        "summary": "The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it.",
        "value": {
          "error": {
            "code": "rate_limited",
            "message": "The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 429,
            "retryable": true,
            "param": null,
            "remediation": "Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "doc_url": "https://socialtap.dev/docs/errors/#rate_limited",
            "details": {},
            "charged": false
          }
        }
      },
      "spend_limit_reached": {
        "summary": "The API key reached its spend limit for this period. The account may still have credits.",
        "value": {
          "error": {
            "code": "spend_limit_reached",
            "message": "The API key reached its spend limit for this period. The account may still have credits.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 402,
            "retryable": false,
            "param": null,
            "remediation": "Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "doc_url": "https://socialtap.dev/docs/errors/#spend_limit_reached",
            "details": {},
            "charged": false
          }
        }
      },
      "unauthorized": {
        "summary": "The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired.",
        "value": {
          "error": {
            "code": "unauthorized",
            "message": "The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 401,
            "retryable": false,
            "param": null,
            "remediation": "Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "doc_url": "https://socialtap.dev/docs/errors/#unauthorized",
            "details": {},
            "charged": false
          }
        }
      },
      "upstream_blocked": {
        "summary": "The platform refused every attempt, our own retries included.",
        "value": {
          "error": {
            "code": "upstream_blocked",
            "message": "The platform refused every attempt, our own retries included.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 503,
            "retryable": true,
            "param": null,
            "remediation": "Retry later with backoff. Failed requests are free.",
            "doc_url": "https://socialtap.dev/docs/errors/#upstream_blocked",
            "details": {},
            "charged": false
          }
        }
      },
      "upstream_error": {
        "summary": "The platform failed, or answered with something we could not read.",
        "value": {
          "error": {
            "code": "upstream_error",
            "message": "The platform failed, or answered with something we could not read.",
            "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
            "status": 502,
            "retryable": true,
            "param": null,
            "remediation": "Retry with backoff. Failed requests are free.",
            "doc_url": "https://socialtap.dev/docs/errors/#upstream_error",
            "details": {},
            "charged": false
          }
        }
      }
    },
    "headers": {
      "age": {
        "description": "Seconds since the data was fetched (cache hits only).",
        "schema": {
          "type": "integer"
        }
      },
      "allow": {
        "description": "Methods the endpoint accepts (method_not_allowed only).",
        "schema": {
          "type": "string"
        }
      },
      "deprecation": {
        "description": "RFC 9745: the endpoint is deprecated, as of this date (@<unix seconds>; may be in the future). Also in meta.warnings.",
        "schema": {
          "type": "string"
        }
      },
      "idempotent-replayed": {
        "description": "true when the answer replays an earlier request with the same Idempotency-Key (it shows the resource's current state).",
        "schema": {
          "type": "boolean"
        }
      },
      "link": {
        "description": "RFC 8288 links: rel=\"next\" is the next page of a list (while page.has_more), the same request with cursor set; rel=\"deprecation\" is a deprecated endpoint's notice.",
        "schema": {
          "type": "string"
        }
      },
      "location": {
        "description": "On 202 answers: the job's URL (GET it, free, for its status).",
        "schema": {
          "type": "string"
        }
      },
      "preference-applied": {
        "description": "RFC 7240: respond-async when Prefer: respond-async turned the request into a job (202).",
        "schema": {
          "type": "string"
        }
      },
      "ratelimit": {
        "description": "What is left of the ceiling (IETF RateLimit field): \"account\";r=<requests that may be sent at once now>;t=<seconds until the bucket is full again>.",
        "schema": {
          "type": "string"
        }
      },
      "ratelimit-policy": {
        "description": "The account's runaway-protection ceiling as an IETF RateLimit-Policy field, as enforced: a token bucket of q requests (twice the ceiling in requests per second, at least 10) that refills in w seconds: \"account\";q=<requests>;w=<seconds>. Not a plan limit.",
        "schema": {
          "type": "string"
        }
      },
      "retry-after": {
        "description": "Seconds to wait before retrying; sent only with the codes whose retry_after is set in the error codes list (never on credit errors).",
        "schema": {
          "type": "integer"
        }
      },
      "sunset": {
        "description": "RFC 8594: when a deprecated endpoint stops answering (HTTP-date); from then on it answers endpoint_retired.",
        "schema": {
          "type": "string"
        }
      },
      "x-client-request-id": {
        "description": "Your x-client-request-id, echoed (also meta.client_request_id).",
        "schema": {
          "type": "string"
        }
      },
      "x-credits-charged": {
        "description": "Credits charged for this request (0 for errors and cache hits).",
        "schema": {
          "type": "integer"
        }
      },
      "x-credits-remaining": {
        "description": "Account balance after this request; for a busy account an estimate that may not yet subtract concurrent requests (about a second of usage), never below the real balance.",
        "schema": {
          "type": "integer"
        }
      },
      "x-request-id": {
        "description": "Unique request ID; include it when contacting support.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "AsyncAccepted": {
        "content": {
          "application/json": {
            "schema": {
              "properties": {
                "data": {
                  "properties": {
                    "cancel_requested_at": {
                      "format": "date-time",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "created_at": {
                      "format": "date-time",
                      "type": "string"
                    },
                    "credits": {
                      "properties": {
                        "charged": {
                          "description": "Credits charged so far, each page once (items' prices; failed items are free).",
                          "type": "integer"
                        },
                        "max": {
                          "description": "max_credits: the most the job may spend.",
                          "type": "integer"
                        },
                        "reserved": {
                          "description": "Credits its running pages may still use (0 once the job ends).",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "max",
                        "reserved",
                        "charged"
                      ],
                      "type": "object"
                    },
                    "expires_at": {
                      "description": "The deadline: items not ended by then expire.",
                      "format": "date-time",
                      "type": "string"
                    },
                    "finished_at": {
                      "description": "When the job ended; null while it runs.",
                      "format": "date-time",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "id": {
                      "description": "The job ID (job_…).",
                      "type": "string"
                    },
                    "max_age": {
                      "description": "The job's max_age; null when it accepts no cached results.",
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "metadata": {
                      "additionalProperties": {
                        "type": "string"
                      },
                      "description": "Your metadata; {} when none.",
                      "type": "object"
                    },
                    "object": {
                      "description": "Always job.",
                      "enum": [
                        "job"
                      ],
                      "type": "string"
                    },
                    "request_counts": {
                      "properties": {
                        "canceled": {
                          "type": "integer"
                        },
                        "expired": {
                          "type": "integer"
                        },
                        "failed": {
                          "type": "integer"
                        },
                        "queued": {
                          "description": "Not started.",
                          "type": "integer"
                        },
                        "running": {
                          "description": "Started (fetching, waiting for a retry or walking pages).",
                          "type": "integer"
                        },
                        "succeeded": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "total",
                        "queued",
                        "running",
                        "succeeded",
                        "failed",
                        "canceled",
                        "expired"
                      ],
                      "type": "object"
                    },
                    "results_expire_at": {
                      "description": "When results are deleted; null while the job runs.",
                      "format": "date-time",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "results_url": {
                      "description": "Every result as JSON Lines (one JobResult per line), signed: works without the API key until results_url_expires_at. Null until the job ends and after results_expire_at.",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "results_url_expires_at": {
                      "format": "date-time",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "started_at": {
                      "description": "When the first item started; null before.",
                      "format": "date-time",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "description": "queued: nothing started yet. running. canceling: canceled, running items finishing. completed: every item ended (check request_counts: there is no job-level failure). canceled. expired: the deadline passed; unfinished items expired.",
                      "enum": [
                        "queued",
                        "running",
                        "canceling",
                        "completed",
                        "canceled",
                        "expired"
                      ],
                      "type": "string"
                    },
                    "webhook_url": {
                      "description": "The job's own webhook URL; null when none.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "status",
                    "request_counts",
                    "credits",
                    "max_age",
                    "metadata",
                    "webhook_url",
                    "created_at",
                    "started_at",
                    "finished_at",
                    "cancel_requested_at",
                    "expires_at",
                    "results_url",
                    "results_url_expires_at",
                    "results_expire_at"
                  ],
                  "type": "object"
                },
                "meta": {
                  "properties": {
                    "client_request_id": {
                      "description": "Your x-client-request-id, echoed; null when you sent none.",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "credits_charged": {
                      "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                      "type": "integer"
                    },
                    "credits_remaining": {
                      "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "request_id": {
                      "description": "Unique request ID; include it when contacting support.",
                      "type": "string"
                    },
                    "warnings": {
                      "description": "Things to act on that did not fail the request. [] when none.",
                      "items": {
                        "properties": {
                          "code": {
                            "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                            "type": "string"
                          },
                          "doc_url": {
                            "description": "Where to read more (the changelog entry, the endpoint's docs).",
                            "type": "string"
                          },
                          "fields": {
                            "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                            "items": {
                              "type": "string"
                            },
                            "type": "array"
                          },
                          "message": {
                            "description": "What to do about it.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "code",
                          "message",
                          "doc_url"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    }
                  },
                  "required": [
                    "request_id",
                    "credits_charged",
                    "credits_remaining",
                    "client_request_id",
                    "warnings"
                  ],
                  "type": "object"
                }
              },
              "required": [
                "data",
                "meta"
              ],
              "type": "object"
            }
          }
        },
        "description": "Accepted (only with `prefer: respond-async`): the request runs as a one-request job (`custom_id` \"request\", the `jobs` scope); its result is the job's result, priced as this request.",
        "headers": {
          "location": {
            "$ref": "#/components/headers/location"
          },
          "preference-applied": {
            "$ref": "#/components/headers/preference-applied"
          },
          "x-credits-charged": {
            "$ref": "#/components/headers/x-credits-charged"
          },
          "x-credits-remaining": {
            "$ref": "#/components/headers/x-credits-remaining"
          },
          "x-request-id": {
            "$ref": "#/components/headers/x-request-id"
          }
        }
      }
    },
    "schemas": {
      "Ad": {
        "properties": {
          "advertiser": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "The advertising page, business or account."
          },
          "approximate_fields": {
            "description": "JSON paths of values that are rounded, date-only or parsed from display text. A list path (external_links) means the list may be incomplete. [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "audience_size": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Range"
              },
              {
                "type": "null"
              }
            ],
            "description": "Estimated target audience size range; null when not disclosed."
          },
          "country_codes": {
            "description": "ISO 3166-1 alpha-2 countries where it was shown; [] if not disclosed.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "creatives": {
            "description": "The ad's creatives: one per card of a carousel and per variation of a dynamic or catalog ad, else one for the ad itself; [] if none are shown.",
            "items": {
              "$ref": "#/components/schemas/AdCreative"
            },
            "type": "array"
          },
          "first_shown_at": {
            "description": "First delivery, RFC 3339 UTC (often date-only: see approximate_fields).",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Library ad ID (string).",
            "type": "string"
          },
          "impressions": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Range"
              },
              {
                "type": "null"
              }
            ],
            "description": "Impressions or times shown range; null when not disclosed."
          },
          "is_active": {
            "description": "True while the ad is running.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_political": {
            "description": "Categorized as a political or social-issue ad; false when the library files it under another category, null when it shows none.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "languages": {
            "description": "BCP-47 languages of the ad; [] if not disclosed.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "last_shown_at": {
            "description": "Last delivery, RFC 3339 UTC; null while active.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "paid_by": {
            "description": "Disclosed payer (\"Paid for by\").",
            "type": [
              "string",
              "null"
            ]
          },
          "platform": {
            "description": "Library owner's platform ID (facebook for Meta's library, tiktok, google, linkedin).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/AdPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "publisher_platforms": {
            "description": "Where it ran, lowercase IDs (facebook, instagram, messenger, audience_network, youtube, …); [] if not disclosed.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "reach": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Range"
              },
              {
                "type": "null"
              }
            ],
            "description": "Unique users reached range; null when not disclosed."
          },
          "spend": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/MoneyRange"
              },
              {
                "type": "null"
              }
            ],
            "description": "Spend range; null when not disclosed."
          },
          "type": {
            "description": "Creative shape. New values may be added; treat unknown values as other.",
            "enum": [
              "image",
              "video",
              "carousel",
              "text",
              "dynamic",
              "other"
            ],
            "type": "string"
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Public library page of the ad.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "url",
          "advertiser",
          "paid_by",
          "is_active",
          "first_shown_at",
          "last_shown_at",
          "type",
          "publisher_platforms",
          "creatives",
          "languages",
          "country_codes",
          "is_political",
          "impressions",
          "reach",
          "audience_size",
          "spend",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "AdCreative": {
        "properties": {
          "body": {
            "description": "Primary text.",
            "type": [
              "string",
              "null"
            ]
          },
          "cta_text": {
            "description": "Call-to-action label (e.g. Shop now).",
            "type": [
              "string",
              "null"
            ]
          },
          "link_description": {
            "description": "Link description text.",
            "type": [
              "string",
              "null"
            ]
          },
          "link_url": {
            "description": "Destination URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "media": {
            "description": "Images and videos of this creative; [] if none.",
            "items": {
              "$ref": "#/components/schemas/Media"
            },
            "type": "array"
          },
          "title": {
            "description": "Headline.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "title",
          "body",
          "link_url",
          "link_description",
          "cta_text",
          "media"
        ],
        "type": "object"
      },
      "AdPlatformSpecific": {
        "properties": {
          "facebook": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookAdSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Meta Ad Library ad's own fields."
          },
          "google": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/GoogleAdSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Google ad's own fields."
          },
          "linkedin": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A LinkedIn Ad Library ad's own fields."
          },
          "tiktok": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokAdSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A TikTok ad's own fields."
          }
        },
        "type": "object"
      },
      "Album": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values that are date-only, rounded by the platform or parsed from display text (released_at from a date, duration_ms from \"1 hour 1 minute\"). A list path means the list may be incomplete. [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "artist_name": {
            "description": "Who the platform credits for the release, as one display string (it can name more people than have an account linked: artists holds the linked ones); null when the source does not name them.",
            "type": [
              "string",
              "null"
            ]
          },
          "artists": {
            "description": "The platform accounts of the artists credited on the release, main artist first, in the platform's order; [] when none is linked, as on a Various Artists compilation (listed in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "copyrights": {
            "description": "The release's copyright lines as the platform shows them; [] when none.",
            "items": {
              "$ref": "#/components/schemas/AlbumCopyright"
            },
            "type": "array"
          },
          "cover_url": {
            "description": "Cover art URL at the largest size the platform serves; null when it has none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "description": "About the release, as plain text (the service's editorial notes, or what its uploader wrote); null when it has none or the platform shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "duration_ms": {
            "description": "Total length of the release in milliseconds; null when neither the platform nor a complete tracks list gives it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "genres": {
            "description": "Genres the platform files it under, as shown (not normalized), the main one first; [] when none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "id": {
            "description": "Platform-native album ID (string), the one in its page's URL.",
            "type": "string"
          },
          "is_explicit": {
            "description": "Marked as holding explicit content (by the platform, or on any of its tracks); null when the platform does not say.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "label": {
            "description": "The record label as the platform names it; null when none is shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/AlbumMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "platform": {
            "description": "Platform ID (applemusic, spotify, soundcloud, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/AlbumPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "released_at": {
            "description": "When it was released, RFC 3339 UTC. A release date with no time (nearly all) is midnight UTC of that date, listed in approximate_fields, and so is a year or month alone (its first day). Null when the platform states none.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The release's title as the platform shows it (with an edition or a suffix like \"- Single\" where it writes one).",
            "type": "string"
          },
          "tracks": {
            "description": "The release's tracks in album order (by disc, then track number). A list of albums, whose source shows none, answers [] and lists tracks in unknown_fields; a list the source could only read part of is listed in approximate_fields.",
            "items": {
              "$ref": "#/components/schemas/AlbumTrack"
            },
            "type": "array"
          },
          "type": {
            "description": "What kind of release it is, as the platform says: album, single, ep or compilation; null when the platform does not say. New values may be added; treat unknown values as album.",
            "enum": [
              "album",
              "single",
              "ep",
              "compilation",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them), tracks[].artists for that list on every track; null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "upc": {
            "description": "The release's barcode: its UPC or EAN, digits only; null when the platform does not show it.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Canonical album page URL.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "url",
          "type",
          "title",
          "description",
          "artist_name",
          "artists",
          "cover_url",
          "released_at",
          "label",
          "upc",
          "copyrights",
          "genres",
          "is_explicit",
          "duration_ms",
          "tracks",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "AlbumCopyright": {
        "properties": {
          "text": {
            "description": "The line as the platform shows it.",
            "type": "string"
          },
          "type": {
            "description": "c: the copyright in the work (©); p: in the sound recording (℗); null when the line does not say or states both. New values may be added.",
            "enum": [
              "c",
              "p",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "type",
          "text"
        ],
        "type": "object"
      },
      "AlbumMetrics": {
        "properties": {
          "track_count": {
            "description": "Tracks on the release as the platform counts them, null when it does not state a count; tracks answers fewer only when listed in approximate_fields or unknown_fields.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "track_count"
        ],
        "type": "object"
      },
      "AlbumPlatformSpecific": {
        "properties": {
          "applemusic": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApplemusicAlbumSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Apple Music album's own fields."
          },
          "soundcloud": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SoundcloudAlbumSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A SoundCloud album set's own fields."
          },
          "spotify": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SpotifyAlbumSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Spotify release's own fields."
          }
        },
        "type": "object"
      },
      "AlbumTrack": {
        "properties": {
          "artist_name": {
            "description": "Who the platform credits for this track, as one display string (a feature included); null when the source does not name them.",
            "type": [
              "string",
              "null"
            ]
          },
          "artists": {
            "description": "The platform accounts of the artists credited on this track, in the platform's order; [] when none is linked (listed in unknown_fields as tracks[].artists when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "disc_number": {
            "description": "The disc it is on, from 1; null when the platform does not say (a release of one disc, on platforms without discs).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "duration_ms": {
            "description": "Length of the track in milliseconds; null when the source does not state it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native track ID (string): the one the platform's track endpoint takes and answers.",
            "type": "string"
          },
          "is_explicit": {
            "description": "Marked as explicit by the platform; null when it does not say.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "isrc": {
            "description": "International Standard Recording Code, 12 characters without hyphens; null when the platform does not show it.",
            "type": [
              "string",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/AlbumTrackMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "play_url": {
            "description": "Audio file URL: a short preview, where the platform serves only one. Signed links expire within hours; null when not exposed.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The track's title as the platform shows it; null when the source names the track only by its ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "track_number": {
            "description": "Its position on its disc, from 1; null when the source does not state it (tracks stay in album order).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "url": {
            "description": "The track's page; null when the source does not show it.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "artist_name",
          "artists",
          "track_number",
          "disc_number",
          "duration_ms",
          "is_explicit",
          "isrc",
          "play_url",
          "metrics"
        ],
        "type": "object"
      },
      "AlbumTrackMetrics": {
        "properties": {
          "view_count": {
            "description": "Plays; null when the platform does not show them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "view_count"
        ],
        "type": "object"
      },
      "AmazonCaptionTrack": {
        "properties": {
          "language": {
            "description": "Language code (en, …).",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "WebVTT file URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "language",
          "url"
        ],
        "type": "object"
      },
      "AmazonCategory": {
        "properties": {
          "id": {
            "description": "Amazon's browse node ID of the category (what its category pages take as node=); null when the link names none.",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "Category name, as shown.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name"
        ],
        "type": "object"
      },
      "AmazonContributor": {
        "properties": {
          "name": {
            "description": "The contributor's name, as the byline shows it.",
            "type": "string"
          },
          "role": {
            "description": "Their role, as Amazon words it (Author, Narrator, Translator); null when the byline gives none.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "role"
        ],
        "type": "object"
      },
      "AmazonCuration": {
        "properties": {
          "id": {
            "description": "Amazon's ID of the curation, as its link writes it (a UUID).",
            "type": "string"
          },
          "post_count": {
            "description": "Posts in it, as its card counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "Its cover image URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "Its title, as the influencer wrote it.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Its link.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "id",
          "title",
          "url",
          "thumbnail_url",
          "post_count"
        ],
        "type": "object"
      },
      "AmazonDeal": {
        "properties": {
          "badge": {
            "description": "The deal's badge, as shown (23% off, Up to 40% off); null when it shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "claimed_percent": {
            "description": "Share of the deal's units already claimed, in percent (0 to 100) as Amazon rounds it; null when Amazon shows none (most deals but lightning deals).",
            "format": "double",
            "maximum": 100,
            "minimum": 0,
            "type": [
              "number",
              "null"
            ]
          },
          "coupon_id": {
            "description": "Amazon's ID of the coupon's promotion (its page is amazon.com/promo/<id>); null when the product has no coupon.",
            "type": [
              "string",
              "null"
            ]
          },
          "coupon_price": {
            "description": "The price after the product's clippable coupon, in major units of the product's currency; null when it has no coupon or the coupon shows no price.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "department_ids": {
            "description": "The browse nodes Amazon's deals list files the deal under, in no particular order (one to several, from a department down to a sub-category): each is a category the Amazon Deals API takes. Empty when it names none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "ends_at": {
            "description": "When the deal ends, RFC 3339 UTC, from the badge's countdown; null when the badge shows none (most deals but lightning deals).",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Amazon's ID of the deal; null for a product listed for its coupon alone.",
            "type": [
              "string",
              "null"
            ]
          },
          "label": {
            "description": "The deal's label, as shown (Limited time deal, Early Black Friday Deal, Limited Prime deal); null when the badge shows a countdown instead (see ends_at) or nothing.",
            "type": [
              "string",
              "null"
            ]
          },
          "original_price_label": {
            "description": "What original_price is: list (the list price), typical (the typical price of the last 90 days), rrp (the recommended retail price) or was (the price before the deal); null when no earlier price is shown or Amazon labels it otherwise. New values may be added; treat unknown values as null.",
            "enum": [
              "list",
              "typical",
              "rrp",
              "was",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "description": "The deal's state, as Amazon names it, lowercased (available: it can be bought at the deal price now); null for a coupon alone.",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "The kind of deal, as Amazon names it, lowercased: lightning_deal (a limited number of units for a few hours), best_deal (a limited time deal), others as Amazon adds them; coupon when the product is listed for its coupon alone.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "status",
          "badge",
          "label",
          "ends_at",
          "claimed_percent",
          "original_price_label",
          "department_ids",
          "coupon_price",
          "coupon_id"
        ],
        "type": "object"
      },
      "AmazonDeal_productsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 100), Amazon's Today's Deals order (its own ranking, as the grid shows it).",
            "items": {
              "$ref": "#/components/schemas/Product"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "AmazonOfferSpecific": {
        "properties": {
          "condition_note": {
            "description": "The seller's or Amazon's notes on the item's condition (Item will come in original packaging.), as shown under it; null when none is shown, as on new offers.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_fulfilled_by_amazon": {
            "description": "Amazon ships the offer from its own warehouses (Fulfillment by Amazon, or sold by Amazon); false when the seller ships it; null when not shown.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "seller_positive_percent": {
            "description": "Share of the seller's ratings in the last 12 months that were positive, a whole percent (77); over the seller's lifetime for a seller Amazon shows that for (a new one); null when not shown (Amazon's own retail shows none).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "ships_from": {
            "description": "Who ships the offer (Amazon, or the seller), as the offer says; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "ships_from",
          "is_fulfilled_by_amazon",
          "seller_positive_percent",
          "condition_note"
        ],
        "type": "object"
      },
      "AmazonOffersResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 11), The buy box offer first, then every other offer in Amazon's order: by price plus delivery, lowest first.",
            "items": {
              "$ref": "#/components/schemas/Offer"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "AmazonPlaylistSpecific": {
        "properties": {
          "heart_count": {
            "description": "Hearts shoppers gave the list (Amazon's likes), exact.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_pinned": {
            "description": "True when the influencer pinned the list to the top of its storefront.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "product_count": {
            "description": "Products in the list, as its card counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "products": {
            "description": "The list's first products as its card shows them (up to 20), in its order; the path is in approximate_fields when the list holds more.",
            "items": {
              "$ref": "#/components/schemas/AmazonProductRef"
            },
            "type": "array"
          }
        },
        "required": [
          "product_count",
          "heart_count",
          "is_pinned",
          "products"
        ],
        "type": "object"
      },
      "AmazonPostSpecific": {
        "properties": {
          "caption_tracks": {
            "description": "The video's caption tracks (WebVTT, public); [] when none, and for photos.",
            "items": {
              "$ref": "#/components/schemas/AmazonCaptionTrack"
            },
            "type": "array"
          },
          "products": {
            "description": "The products the post tags, in its order; [] when none. The path is in approximate_fields when the post may tag more than it shows.",
            "items": {
              "$ref": "#/components/schemas/AmazonProductRef"
            },
            "type": "array"
          }
        },
        "required": [
          "products",
          "caption_tracks"
        ],
        "type": "object"
      },
      "AmazonProductMetrics": {
        "properties": {
          "bought_past_month_count": {
            "description": "Units bought in the past month as Amazon's badge rounds them (10K+ is 10000): a lower bound; null when the page shows no badge.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "offer_count": {
            "description": "Offers from every seller, new and used, as the other sellers box counts them; null when the page shows no such box.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "rating_count": {
            "description": "Customer ratings behind rating (with or without a written review), exact.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "rating_distribution": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RatingDistribution"
              },
              {
                "type": "null"
              }
            ],
            "description": "Ratings per star, from the histogram's whole percentages times rating_count (so each can be off by half a percent of rating_count); null when unrated."
          }
        },
        "required": [
          "rating_count",
          "bought_past_month_count",
          "offer_count",
          "rating_distribution"
        ],
        "type": "object"
      },
      "AmazonProductRef": {
        "properties": {
          "asin": {
            "description": "The product's ASIN (what amazon.product takes).",
            "type": "string"
          },
          "image_url": {
            "description": "The product's image URL, as the card shows it.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The product's page in the list's marketplace.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "asin",
          "url",
          "image_url"
        ],
        "type": "object"
      },
      "AmazonProductResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Product"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "AmazonProductSpecific": {
        "properties": {
          "availability_label": {
            "description": "The buy box's stock line, as Amazon words it (Only 1 left in stock - order soon.); null when the page shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "best_sellers_ranks": {
            "description": "The product's sales rank in each category Amazon ranks it in (#49 in Electronics, #7 in Earbud & In-Ear Headphones), department first; [] when the page shows none.",
            "items": {
              "$ref": "#/components/schemas/AmazonRank"
            },
            "type": "array"
          },
          "brand": {
            "description": "Brand name, as Amazon shows it; null when it shows none (most books: their authors are contributors).",
            "type": [
              "string",
              "null"
            ]
          },
          "categories": {
            "description": "The product's category path, from the department down to category (the last one); [] when the page shows none.",
            "items": {
              "$ref": "#/components/schemas/AmazonCategory"
            },
            "type": "array"
          },
          "contributors": {
            "description": "The people the byline credits (a book's authors, narrators and translators), in Amazon's order; [] when the byline names none.",
            "items": {
              "$ref": "#/components/schemas/AmazonContributor"
            },
            "type": "array"
          },
          "deal": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AmazonDeal"
              },
              {
                "type": "null"
              }
            ],
            "description": "The deal Amazon's deals list shows the product with: its type, badge, end time, share claimed and coupon; null outside a deals list."
          },
          "features": {
            "description": "The \"About this item\" bullet points, in Amazon's order; [] when the page has none (books, most media).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "is_sponsored": {
            "description": "The product is a paid placement among a search's results (Amazon labels it Sponsored); null outside search results.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/AmazonProductMetrics",
            "description": "Counts at fetch time; null = not shown, 0 = zero."
          },
          "parent_asin": {
            "description": "ASIN of the variation family this product belongs to (every color and size of it shares it); null for a product without variations.",
            "type": [
              "string",
              "null"
            ]
          },
          "rank": {
            "description": "Position in the requested Best Sellers or other ranked list (1 = top); null off a list.",
            "format": "int64",
            "minimum": 1,
            "type": [
              "integer",
              "null"
            ]
          },
          "rating": {
            "description": "Average customer rating out of 5 (metrics.rating_count ratings behind it), as Amazon shows it, to one decimal; null when unrated.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "ships_from": {
            "description": "Who ships the featured offer (Amazon, or the seller), as the buy box says; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "variants": {
            "description": "Every variation of the product (its colors, sizes, styles), each an ASIN with its options, in Amazon's order; prices and stock are this product's only, so they are null on variants. [] for a product without variations.",
            "items": {
              "$ref": "#/components/schemas/ProductVariant"
            },
            "type": "array"
          }
        },
        "required": [
          "brand",
          "contributors",
          "rating",
          "metrics",
          "features",
          "is_sponsored",
          "categories",
          "best_sellers_ranks",
          "rank",
          "parent_asin",
          "variants",
          "availability_label",
          "ships_from",
          "deal"
        ],
        "type": "object"
      },
      "AmazonProfileSpecific": {
        "properties": {
          "seller_business": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AmazonSellerBusiness"
              },
              {
                "type": "null"
              }
            ],
            "description": "A seller's business identity, as its page discloses it (by law in the US and the EU): legal name, registration and VAT numbers, phone, email and addresses. Null on an account that is not a seller, or a seller whose page discloses none."
          },
          "seller_feedback": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AmazonSellerFeedback"
              },
              {
                "type": "null"
              }
            ],
            "description": "A seller's feedback from its buyers: the share of positive ratings, and per period its star rating and its ratings per star. Null on an account that is not a seller, or a seller whose page shows no feedback (Amazon's own subsidiaries)."
          },
          "shop": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AmazonStorefront"
              },
              {
                "type": "null"
              }
            ],
            "description": "An influencer's storefront: its Top Creator badge, its curations and its trending picks. Null on an account that is not an influencer (a seller)."
          }
        },
        "required": [
          "seller_feedback",
          "seller_business",
          "shop"
        ],
        "type": "object"
      },
      "AmazonRank": {
        "properties": {
          "category": {
            "description": "Category name, as shown.",
            "type": "string"
          },
          "category_id": {
            "description": "Amazon's ID of the ranking: a browse node ID, or a department's slug (electronics) for a department's rank; null when the row links none.",
            "type": [
              "string",
              "null"
            ]
          },
          "rank": {
            "description": "The product's sales rank in the category (1 is the best seller).",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "rank",
          "category",
          "category_id"
        ],
        "type": "object"
      },
      "AmazonReviewsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 20), Amazon's top reviews: the marketplace's own first, then other countries'.",
            "items": {
              "$ref": "#/components/schemas/Review"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "AmazonSearch_productsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 60), Amazon's Newest Arrivals: the most recently listed first with sort=newest, Amazon's Best Sellers order: the most bought first with sort=popular, the lowest price first with sort=price_asc, the highest price first with sort=price_desc, Amazon's Featured order, sponsored results among them with sort=relevance.",
            "items": {
              "$ref": "#/components/schemas/Product"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "AmazonSellerBusiness": {
        "properties": {
          "address": {
            "description": "Its registered business address on one line, as declared, ending with the country's code; null when not disclosed.",
            "type": [
              "string",
              "null"
            ]
          },
          "business_type": {
            "description": "The kind of business, as Amazon words it (Privately-owned business, Sole proprietorship); null when not disclosed (US marketplaces show none).",
            "type": [
              "string",
              "null"
            ]
          },
          "customer_service_address": {
            "description": "The address it gives for customer service on one line, when it gives one apart from the business address; null otherwise.",
            "type": [
              "string",
              "null"
            ]
          },
          "customer_service_phone": {
            "description": "The customer service phone number its page shows beside Ask a question, as written; null when it shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "description": "The business email address it declared; null when not disclosed.",
            "type": [
              "string",
              "null"
            ]
          },
          "legal_name": {
            "description": "The seller's registered business name, as declared (its display name is the shop's); null when not disclosed.",
            "type": [
              "string",
              "null"
            ]
          },
          "phone": {
            "description": "The business phone number it declared, as written; null when not disclosed.",
            "type": [
              "string",
              "null"
            ]
          },
          "trade_register_number": {
            "description": "Its commercial register number, as declared (HRB 40534); null when not disclosed.",
            "type": [
              "string",
              "null"
            ]
          },
          "vat_number": {
            "description": "Its VAT identification number (DE453729570); null when not disclosed.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "legal_name",
          "business_type",
          "trade_register_number",
          "vat_number",
          "phone",
          "email",
          "address",
          "customer_service_address",
          "customer_service_phone"
        ],
        "type": "object"
      },
      "AmazonSellerFeedback": {
        "properties": {
          "last_12_months": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AmazonSellerRatings"
              },
              {
                "type": "null"
              }
            ],
            "description": "Ratings from the last 12 months; null when the page shows none."
          },
          "last_30_days": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AmazonSellerRatings"
              },
              {
                "type": "null"
              }
            ],
            "description": "Ratings from the last 30 days (the page's 1 month); null when the page shows none."
          },
          "last_90_days": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AmazonSellerRatings"
              },
              {
                "type": "null"
              }
            ],
            "description": "Ratings from the last 90 days (the page's 3 months); null when the page shows none."
          },
          "lifetime": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AmazonSellerRatings"
              },
              {
                "type": "null"
              }
            ],
            "description": "Every rating the seller has received; null when the page shows none."
          },
          "positive_percent": {
            "description": "Share of the last 12 months' ratings that are positive (4 or 5 stars), as Amazon rounds it to a whole percent; null when the page shows none (no ratings in the last 12 months).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "positive_percent",
          "last_30_days",
          "last_90_days",
          "last_12_months",
          "lifetime"
        ],
        "type": "object"
      },
      "AmazonSellerRatings": {
        "properties": {
          "rating": {
            "description": "Star rating out of 5 over the period, as Amazon shows it, to one decimal; null when the period has no ratings.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "rating_count": {
            "description": "Ratings buyers gave the seller over the period, exact.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "rating_distribution": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RatingDistribution"
              },
              {
                "type": "null"
              }
            ],
            "description": "Ratings per star over the period, exact; null when the page does not count them."
          },
          "review_count": {
            "description": "Ratings that came with a written review, exact; null when the page does not count them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "rating",
          "rating_count",
          "review_count",
          "rating_distribution"
        ],
        "type": "object"
      },
      "AmazonSellerResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "AmazonShopResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "AmazonShop_listsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 20), the storefront's order: the list created or changed most recently first, with the lists the influencer pinned at the top of the first page.",
            "items": {
              "$ref": "#/components/schemas/Playlist"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "AmazonShop_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 20), the storefront's: newest first within each tab, after the posts the influencer pinned; type=all lists the videos, then the photos. In Amazon's words: `metrics.like_count` is hearts.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "AmazonStorefront": {
        "properties": {
          "curations": {
            "description": "Its curations, named collections of its posts, in the storefront's order; [] when it has none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/AmazonCuration"
            },
            "type": "array"
          },
          "is_top_creator": {
            "description": "True when Amazon shows its Top Creator badge (a leading Amazon creator by customer engagement and sales), false when it shows none; null when unknown.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "trending_picks": {
            "description": "The products Amazon shows as trending from this storefront, in its order; [] when it shows none.",
            "items": {
              "$ref": "#/components/schemas/AmazonTrendingPick"
            },
            "type": "array"
          }
        },
        "required": [
          "is_top_creator",
          "curations",
          "trending_picks"
        ],
        "type": "object"
      },
      "AmazonTop_productsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), Amazon's rank in the list (1 = top).",
            "items": {
              "$ref": "#/components/schemas/Product"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "AmazonTrendingPick": {
        "properties": {
          "asin": {
            "description": "The product's ASIN (what amazon.product takes).",
            "type": "string"
          },
          "badge": {
            "description": "The badge on its card, as shown (Deal); null when it has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "currency": {
            "description": "ISO 4217 code of price; null when there is no price.",
            "type": [
              "string",
              "null"
            ]
          },
          "image_url": {
            "description": "The product's image URL, as the card shows it.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "price": {
            "description": "Its current price in major units of currency, as the card shows it; null when it shows none (no offer).",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "url": {
            "description": "The product's page in the storefront's marketplace.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "asin",
          "url",
          "image_url",
          "price",
          "currency",
          "badge"
        ],
        "type": "object"
      },
      "ApplemusicAlbumResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Album"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "ApplemusicAlbumSpecific": {
        "properties": {
          "audio_traits": {
            "description": "The audio formats it comes in (atmos, lossless, lossy-stereo, spatial, …); [] when none or the source does not show them (listed in unknown_fields). New values may be added.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "content_rating": {
            "description": "explicit, or clean for an edited version of something explicit; null when Apple marks neither.",
            "type": [
              "string",
              "null"
            ]
          },
          "editorial_summary": {
            "description": "Apple's one-line note on the album; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_complete": {
            "description": "Every track of the release is available in this store.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_mastered_for_itunes": {
            "description": "Carries Apple's Mastered for iTunes badge, which Apple now calls Apple Digital Master.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_prerelease": {
            "description": "Announced, and not released yet.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "more_by_artist": {
            "description": "Apple's other releases by the same artist, as many as its page shows at first; [] when none or the source does not show them (listed in unknown_fields).",
            "items": {
              "$ref": "#/components/schemas/ApplemusicItem"
            },
            "type": "array"
          },
          "other_versions": {
            "description": "Other versions of the release (the clean or explicit one, a deluxe edition); [] when none or the source does not show them (listed in unknown_fields).",
            "items": {
              "$ref": "#/components/schemas/ApplemusicItem"
            },
            "type": "array"
          },
          "rank": {
            "description": "Position on the requested chart (1 = top); null off a chart.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "storefront": {
            "description": "The Apple Music store this answer is from, as a lowercase country code (us, jp): titles, availability, track lists and links differ by store.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "storefront",
          "rank",
          "editorial_summary",
          "content_rating",
          "audio_traits",
          "is_complete",
          "is_prerelease",
          "is_mastered_for_itunes",
          "more_by_artist",
          "other_versions"
        ],
        "type": "object"
      },
      "ApplemusicArtistResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "ApplemusicItem": {
        "properties": {
          "artist_name": {
            "description": "Who Apple credits for it, or a playlist's curator; null on an artist.",
            "type": [
              "string",
              "null"
            ]
          },
          "cover_url": {
            "description": "Its artwork at the largest size Apple states; null when none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "duration_ms": {
            "description": "A song's or music video's length in milliseconds, null on other kinds.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "id": {
            "description": "Apple Music's ID of the item (string).",
            "type": "string"
          },
          "is_explicit": {
            "description": "Apple marks it explicit; null on kinds it does not mark.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "kind": {
            "description": "What it is. New values may be added.",
            "enum": [
              "song",
              "music_video",
              "album",
              "playlist",
              "artist",
              "station"
            ],
            "type": "string"
          },
          "released_at": {
            "description": "Its release date, midnight UTC of that date; null when Apple does not state it.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "Its title, or an artist's name.",
            "type": [
              "string",
              "null"
            ]
          },
          "track_count": {
            "description": "An album's tracks, null on other kinds.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "url": {
            "description": "Its page; null when Apple does not state it.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "kind",
          "url",
          "title",
          "artist_name",
          "cover_url",
          "released_at",
          "track_count",
          "duration_ms",
          "is_explicit"
        ],
        "type": "object"
      },
      "ApplemusicPlaylistSpecific": {
        "properties": {
          "audio_traits": {
            "description": "The audio formats the playlist comes in; [] on a station or when none. New values may be added.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "band": {
            "description": "How a live station is carried, as Apple says: FM, AM, DAB, Sat, Stream, …; null when it says nothing, and on a playlist. New values may be added.",
            "type": [
              "string",
              "null"
            ]
          },
          "curator_id": {
            "description": "Apple's ID of the playlist's curator; null when none is linked, as on a station.",
            "type": [
              "string",
              "null"
            ]
          },
          "editorial_kind": {
            "description": "What Apple says an editorial playlist is built around: artist-franchise (one artist, such as their Essentials or a set list); null when it says nothing, and on a station. New values may be added.",
            "type": [
              "string",
              "null"
            ]
          },
          "editorial_sub_kind": {
            "description": "Apple's finer word for that: artist-set-list, artist-created-set-list; null when it says nothing, and on a station. New values may be added.",
            "type": [
              "string",
              "null"
            ]
          },
          "editorial_summary": {
            "description": "Apple's one-line note on it; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "frequency": {
            "description": "A broadcast station's frequency as Apple states it, in its band's usual unit (90.1 on FM, 1026 on AM); a station on several frequencies lists them separated by / (105.1/105.3/105.7); null when it states none, and on a playlist.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_chart": {
            "description": "The playlist is one of Apple's charts; null on a station.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_collaborative": {
            "description": "Several people edit the playlist; null on a station.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_live": {
            "description": "A station that streams live rather than picking songs; null on a playlist.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_subscription_required": {
            "description": "A station only subscribers can play; null on a playlist.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "last_modified_at": {
            "description": "When the playlist last changed, RFC 3339 UTC; null on a station.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "media_kind": {
            "description": "A station's medium, audio or video; null on a playlist.",
            "type": [
              "string",
              "null"
            ]
          },
          "playlist_type": {
            "description": "Who makes the playlist, as Apple says: editorial, external (a curator's), personal-mix, user-shared, …; null on a station. New values may be added.",
            "type": [
              "string",
              "null"
            ]
          },
          "rank": {
            "description": "Position on the requested chart (1 = top); null off a chart.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "station_kind": {
            "description": "A station's kind as Apple says: streaming (a live stream), artistOnly, songSeeded, …; null on a playlist. New values may be added.",
            "type": [
              "string",
              "null"
            ]
          },
          "storefront": {
            "description": "The Apple Music store this answer is from, as a lowercase country code (us, jp).",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "storefront",
          "rank",
          "editorial_summary",
          "curator_id",
          "playlist_type",
          "editorial_kind",
          "editorial_sub_kind",
          "last_modified_at",
          "is_chart",
          "is_collaborative",
          "audio_traits",
          "station_kind",
          "media_kind",
          "band",
          "frequency",
          "is_live",
          "is_subscription_required"
        ],
        "type": "object"
      },
      "ApplemusicPostSpecific": {
        "properties": {
          "air_ended_at": {
            "description": "When a radio episode's broadcast ended, RFC 3339 UTC; null on other posts.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "album_artist_name": {
            "description": "Who Apple credits for the album it is on (Various Artists on a compilation); null when on none.",
            "type": [
              "string",
              "null"
            ]
          },
          "album_id": {
            "description": "The ID of the album it is on (applemusic.album takes it); null for a music video or radio episode on none.",
            "type": [
              "string",
              "null"
            ]
          },
          "album_title": {
            "description": "The title of the album it is on; null when on none.",
            "type": [
              "string",
              "null"
            ]
          },
          "album_url": {
            "description": "The album's page; null when on none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "artist_name": {
            "description": "Who Apple credits for it, as one display string (Lady Gaga & Bradley Cooper), which can name more people than author and coauthors link.",
            "type": [
              "string",
              "null"
            ]
          },
          "attribution": {
            "description": "Who a classical work is attributed to (its composer); null on other music.",
            "type": [
              "string",
              "null"
            ]
          },
          "audio_locale": {
            "description": "The language it is sung or spoken in, as Apple's tag (en-US); null when Apple does not say.",
            "type": [
              "string",
              "null"
            ]
          },
          "audio_traits": {
            "description": "The audio formats it comes in (atmos, lossless, lossy-stereo, spatial, …); [] when none or the source does not show them. New values may be added.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "composer_name": {
            "description": "The writers Apple credits, as one display string; null when none or the source does not show them.",
            "type": [
              "string",
              "null"
            ]
          },
          "content_rating": {
            "description": "explicit, or clean for an edited version of something explicit; null when Apple marks neither.",
            "type": [
              "string",
              "null"
            ]
          },
          "curator_id": {
            "description": "Apple's ID of a radio episode's show, which is a curator and no artist; null on other posts.",
            "type": [
              "string",
              "null"
            ]
          },
          "disc_number": {
            "description": "The disc of that album it is on, from 1.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "genres": {
            "description": "The genres Apple files it under, as shown in the answer's language, the main one first; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "is_4k": {
            "description": "A music video that comes in 4K; null on a song.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_apple_digital_master": {
            "description": "Carries Apple's Apple Digital Master badge.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_explicit": {
            "description": "Apple marks it explicit.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_hdr": {
            "description": "A music video that comes in HDR; null on a song.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_live": {
            "description": "A radio episode on the air now; null on other posts.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_lyrics_available": {
            "description": "Apple has its lyrics (they are for subscribers: this answer does not hold them).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_mastered_for_itunes": {
            "description": "Carries Apple's Mastered for iTunes badge, which Apple now calls Apple Digital Master.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_time_synced_lyrics_available": {
            "description": "Apple has its lyrics line by line in time with the audio.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "isrc": {
            "description": "International Standard Recording Code, 12 characters without hyphens: what joins a recording across services. Null when the source does not show it.",
            "type": [
              "string",
              "null"
            ]
          },
          "long_note": {
            "description": "A radio episode's longer note, as Apple writes it: often the name of its show, or a shorter or older form of it, and sometimes something else, such as a date; so a hint, not an identity. Null when Apple has none, which depends on the store and language, and on other posts.",
            "type": [
              "string",
              "null"
            ]
          },
          "movement_count": {
            "description": "How many movements the work has.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "movement_name": {
            "description": "The movement of that work; null on other music.",
            "type": [
              "string",
              "null"
            ]
          },
          "movement_number": {
            "description": "That movement's number in the work.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "rank": {
            "description": "Position on the requested chart (1 = top); null off a chart.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "storefront": {
            "description": "The Apple Music store this answer is from, as a lowercase country code (us, jp): titles, availability and links differ by store.",
            "type": [
              "string",
              "null"
            ]
          },
          "track_number": {
            "description": "Its position on that disc, from 1.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "video_traits": {
            "description": "A music video's formats, as Apple names them; [] on a song or when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "work_name": {
            "description": "The classical work this is part of; null on other music.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "storefront",
          "rank",
          "artist_name",
          "album_id",
          "album_title",
          "album_url",
          "album_artist_name",
          "disc_number",
          "track_number",
          "isrc",
          "composer_name",
          "genres",
          "is_explicit",
          "content_rating",
          "audio_traits",
          "audio_locale",
          "is_lyrics_available",
          "is_time_synced_lyrics_available",
          "is_apple_digital_master",
          "is_mastered_for_itunes",
          "work_name",
          "movement_name",
          "movement_number",
          "movement_count",
          "attribution",
          "is_4k",
          "is_hdr",
          "video_traits",
          "curator_id",
          "long_note",
          "air_ended_at",
          "is_live"
        ],
        "type": "object"
      },
      "ApplemusicProfileSpecific": {
        "properties": {
          "albums": {
            "description": "The artist's albums, as many as the page shows at first; [] when none.",
            "items": {
              "$ref": "#/components/schemas/ApplemusicItem"
            },
            "type": "array"
          },
          "amg_artist_id": {
            "description": "The artist's ID at AllMusic (AMG), from the lookup API; null on most answers, from the catalog API.",
            "type": [
              "string",
              "null"
            ]
          },
          "born_or_formed": {
            "description": "When the artist was born or the group formed, as Apple shows it in the answer's language; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "editorial_summary": {
            "description": "Apple's one-line note on the artist; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "genres": {
            "description": "The genres Apple files the artist under, as shown in the answer's language, the main one first; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "is_group": {
            "description": "A band or other group; false for one person; null when Apple does not say.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "latest_release": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApplemusicItem"
              },
              {
                "type": "null"
              }
            ],
            "description": "The artist's latest release as Apple shows it; null when none."
          },
          "music_videos": {
            "description": "The artist's music videos, as many as the page shows at first; [] when none.",
            "items": {
              "$ref": "#/components/schemas/ApplemusicItem"
            },
            "type": "array"
          },
          "playlists": {
            "description": "Playlists Apple makes of the artist, as many as the page shows at first; [] when none.",
            "items": {
              "$ref": "#/components/schemas/ApplemusicItem"
            },
            "type": "array"
          },
          "similar_artists": {
            "description": "Artists Apple lists as similar, as many as the page shows at first; [] when none.",
            "items": {
              "$ref": "#/components/schemas/ApplemusicItem"
            },
            "type": "array"
          },
          "singles": {
            "description": "The artist's singles and EPs, as many as the page shows at first; [] when none.",
            "items": {
              "$ref": "#/components/schemas/ApplemusicItem"
            },
            "type": "array"
          },
          "storefront": {
            "description": "The Apple Music store this answer is from, as a lowercase country code (us, jp): the bio's language, the sections and links differ by store.",
            "type": [
              "string",
              "null"
            ]
          },
          "top_songs": {
            "description": "The artist's top songs, best first, as many as the page shows at first; [] when none.",
            "items": {
              "$ref": "#/components/schemas/ApplemusicItem"
            },
            "type": "array"
          }
        },
        "required": [
          "storefront",
          "genres",
          "is_group",
          "born_or_formed",
          "editorial_summary",
          "amg_artist_id",
          "top_songs",
          "latest_release",
          "albums",
          "singles",
          "music_videos",
          "playlists",
          "similar_artists"
        ],
        "type": "object"
      },
      "ApplemusicSearch_albumsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), Apple Music's own relevance order for the query.",
            "items": {
              "$ref": "#/components/schemas/Album"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "ApplemusicSearch_artistsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), Apple Music's own relevance order for the query.",
            "items": {
              "$ref": "#/components/schemas/Profile"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "ApplemusicSearch_playlistsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), Apple Music's own relevance order for the query.",
            "items": {
              "$ref": "#/components/schemas/Playlist"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "ApplemusicSearch_tracksResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), Apple Music's own relevance order for the query.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "ApplemusicTop_albumsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), Apple Music's own chart order (1 = most played).",
            "items": {
              "$ref": "#/components/schemas/Album"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "ApplemusicTop_playlistsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), Apple Music's own chart order (1 = most played).",
            "items": {
              "$ref": "#/components/schemas/Playlist"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "ApplemusicTop_tracksResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 100), Apple Music's own chart order (1 = most played).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "ApplemusicTrackResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "BlueskyCommentSpecific": {
        "properties": {
          "bridged_from_url": {
            "description": "The link Bridgy Fed records for a reply it brought to Bluesky from the fediverse or the web, usually where it was first published; null when it was written on Bluesky.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "cid": {
            "description": "The content hash (CID) of this version of the reply's record.",
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "description": "The time the reply's own record states, RFC 3339 UTC: the author's client writes it, so it can be earlier than the reply went public.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "embedded_record_uri": {
            "description": "The at:// URI of a custom feed, list or starter pack the reply embeds; null when it embeds none.",
            "type": [
              "string",
              "null"
            ]
          },
          "hashtags": {
            "description": "Hashtags in the reply, without the #; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "indexed_at": {
            "description": "When Bluesky's AppView first saw the reply, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "is_hidden": {
            "description": "Bluesky folds the reply under the thread's \"Show more replies\" button: the post's author hid it, or Bluesky's own ranking set it aside. Null when the thread was read from the route that does not say.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_hidden_by_post_author": {
            "description": "The post's author hid this reply from their thread.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_nsfw": {
            "description": "The reply carries an adult or sensitive label.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "labels": {
            "description": "Moderation and self labels on the reply (porn, sexual, nudity, graphic-media, spam, …), as Bluesky names them; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "languages": {
            "description": "Every language the author tagged the reply with, in the author's order; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "link_card": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BlueskyLinkCard"
              },
              {
                "type": "null"
              }
            ],
            "description": "The link preview card the reply shows; null when none."
          },
          "links": {
            "description": "The full URLs the reply's text links to, in text order; the text itself shows them shortened. [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "media": {
            "description": "The reply's images and video; [] when none.",
            "items": {
              "$ref": "#/components/schemas/Media"
            },
            "type": "array"
          },
          "mentions": {
            "description": "Accounts the reply mentions, by handle; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "quote_count": {
            "description": "Times the reply was quoted in another post; never negative.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "quoted_post": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BlueskyEmbeddedPost"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post this reply quotes, as Bluesky embeds it; null when it quotes none, or when the quoted post was deleted, is blocked, was detached by its author, or is by an account shown only to signed-in people."
          },
          "quoted_post_id": {
            "description": "The at:// ID of the post this reply quotes; null when it quotes none. Stays set when the quoted post can't be shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "reply_root_post_id": {
            "description": "The at:// ID of the post that started the thread: post_id itself unless the post asked about is a reply.",
            "type": [
              "string",
              "null"
            ]
          },
          "repost_count": {
            "description": "Times the reply was reposted; never negative.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "save_count": {
            "description": "Times the reply was bookmarked; never negative.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "repost_count",
          "quote_count",
          "save_count",
          "is_hidden",
          "is_hidden_by_post_author",
          "reply_root_post_id",
          "cid",
          "indexed_at",
          "created_at",
          "languages",
          "labels",
          "is_nsfw",
          "hashtags",
          "mentions",
          "links",
          "media",
          "link_card",
          "quoted_post_id",
          "quoted_post",
          "embedded_record_uri",
          "bridged_from_url"
        ],
        "type": "object"
      },
      "BlueskyCommentsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 1000), newest first with sort=newest, oldest first with sort=oldest, Most liked first, the replies Bluesky folds under \"Show more replies\" last with sort=popular.",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "BlueskyEmbeddedPost": {
        "properties": {
          "author": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "Its author."
          },
          "id": {
            "description": "Its at:// ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "media": {
            "description": "Its images and video; [] when none.",
            "items": {
              "$ref": "#/components/schemas/Media"
            },
            "type": "array"
          },
          "metrics": {
            "$ref": "#/components/schemas/PostMetrics",
            "description": "Its own counts at fetch time."
          },
          "published_at": {
            "description": "When it went public, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "text": {
            "description": "Its text.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Its URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "text",
          "published_at",
          "author",
          "media",
          "metrics"
        ],
        "type": "object"
      },
      "BlueskyLinkCard": {
        "properties": {
          "description": {
            "description": "The card's description.",
            "type": [
              "string",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "The card's image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The card's title.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The page it links to.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "url",
          "title",
          "description",
          "thumbnail_url"
        ],
        "type": "object"
      },
      "BlueskyPostResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "BlueskyPostSpecific": {
        "properties": {
          "bridged_from_url": {
            "description": "The link Bridgy Fed records for a post it brought to Bluesky from the fediverse or the web, usually where the post was first published; null when it was written on Bluesky.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "cid": {
            "description": "The content hash (CID) of this version of the post's record.",
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "description": "The time the post's own record states, RFC 3339 UTC: the author's client writes it, so it can be earlier than the post went public (an imported archive) or later than it; null when it can't be read as a time.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "embedded_record_uri": {
            "description": "The at:// URI of a custom feed, list or starter pack the post embeds; null when it embeds none.",
            "type": [
              "string",
              "null"
            ]
          },
          "indexed_at": {
            "description": "When Bluesky's AppView first saw the post, RFC 3339 UTC; null when the record was read from the account's own repository instead of the AppView.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "labels": {
            "description": "Moderation and self labels on the post (porn, sexual, nudity, graphic-media, spam, …), as Bluesky names them; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "languages": {
            "description": "Every language the author tagged the post with, in the author's order; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "link_card": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BlueskyLinkCard"
              },
              {
                "type": "null"
              }
            ],
            "description": "The link preview card the post shows; null when none."
          },
          "links": {
            "description": "The full URLs the post's text links to, in text order; the text itself shows them shortened. [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "quoted_post": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BlueskyEmbeddedPost"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post this one quotes, as Bluesky embeds it; null when it quotes none, or when the quoted post was deleted, is blocked, was detached by its author, or its author shows it only to signed-in people."
          },
          "quoted_post_id": {
            "description": "The at:// ID of the post this one quotes; null when it quotes none. Stays set when the quoted post can't be shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "reply_root_post_id": {
            "description": "The at:// ID of the post that started the thread; null when this post is not a reply.",
            "type": [
              "string",
              "null"
            ]
          },
          "reply_to_post_id": {
            "description": "The at:// ID of the post this one replies to; null when it is not a reply.",
            "type": [
              "string",
              "null"
            ]
          },
          "reposted_at": {
            "description": "When the account reposted it, RFC 3339 UTC; null when it is the account's own post.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "reposted_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The account whose repost put this post in the list; null when it is the account's own post, and on an endpoint that reads one post."
          }
        },
        "required": [
          "cid",
          "indexed_at",
          "created_at",
          "languages",
          "labels",
          "links",
          "link_card",
          "quoted_post_id",
          "quoted_post",
          "embedded_record_uri",
          "reply_to_post_id",
          "reply_root_post_id",
          "bridged_from_url",
          "reposted_by",
          "reposted_at"
        ],
        "type": "object"
      },
      "BlueskyPostsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 100), most recent activity first: a post by when it was posted, a repost by when it was reposted.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "BlueskyProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "BlueskyProfileSpecific": {
        "properties": {
          "feed_count": {
            "description": "How many custom feeds the account made; null when the public page answered instead of the AppView.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "indexed_at": {
            "description": "When Bluesky's AppView last indexed the account's profile, RFC 3339 UTC; null when the public page answered instead of the AppView.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "is_labeler": {
            "description": "True when the account runs a moderation service that labels other accounts and posts. Null when the public page answered instead of the AppView.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_trusted_verifier": {
            "description": "True when Bluesky trusts this account to verify others; is_verified is then true too. Null when the public page answered instead of the AppView.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "labels": {
            "description": "Moderation and self labels on the account (bot, porn, spam, …), as Bluesky names them; [] when none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "list_count": {
            "description": "How many lists the account made; null when the public page answered instead of the AppView.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "pinned_post_id": {
            "description": "The at:// ID of the post the account pinned, which bluesky.post takes as url; null when it pinned none, or when the public page answered instead of the AppView.",
            "type": [
              "string",
              "null"
            ]
          },
          "pronouns": {
            "description": "The pronouns the account wrote on its profile; null when it wrote none, or when the public page answered instead of the AppView.",
            "type": [
              "string",
              "null"
            ]
          },
          "starter_pack_count": {
            "description": "How many starter packs the account made; null when the public page answered instead of the AppView.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "verified_by": {
            "description": "Who verified this account, each with when; [] when nobody did (listed in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/BlueskyVerification"
            },
            "type": "array"
          }
        },
        "required": [
          "indexed_at",
          "pronouns",
          "is_trusted_verifier",
          "verified_by",
          "pinned_post_id",
          "labels",
          "list_count",
          "feed_count",
          "starter_pack_count",
          "is_labeler"
        ],
        "type": "object"
      },
      "BlueskySearch_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 100), newest first, by the time each post states, to the second with sort=newest, Bluesky's Top ranking with sort=popular.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "BlueskyVerification": {
        "properties": {
          "created_at": {
            "description": "When the verifier made it, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "The at:// URI of the verification record.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_valid": {
            "description": "Whether Bluesky still honors the verification.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "issuer": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "The account that verified this one. is_verified and avatar_url are null: Bluesky names the verifier without them."
          }
        },
        "required": [
          "id",
          "issuer",
          "is_valid",
          "created_at"
        ],
        "type": "object"
      },
      "Comment": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform or parsed from display text. A list path (external_links) means the list may be incomplete. [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "author": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "The commenting account. An account the platform no longer names (a deleted account) has a null id and username and the platform's label as display_name (Reddit: [deleted])."
          },
          "edited_at": {
            "description": "When the comment was last edited, RFC 3339 UTC; null when never edited or when the platform marks edits without a time (see is_edited).",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native comment ID (string; Reddit with its t1_ prefix).",
            "type": "string"
          },
          "is_by_post_author": {
            "description": "Written by the post's author (the creator's own comment, marked as such by the platform).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_edited": {
            "description": "The comment was edited after posting (the platform's edited mark); null when the platform does not say.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_liked_by_author": {
            "description": "Liked or hearted by the post's author.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_pinned": {
            "description": "Pinned by the post's author.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/CommentMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "parent_id": {
            "description": "ID of the comment this replies to; null for top-level comments.",
            "type": [
              "string",
              "null"
            ]
          },
          "platform": {
            "description": "Platform ID (tiktok, youtube, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/CommentPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "post_id": {
            "description": "ID of the post commented on (equals post.id).",
            "type": "string"
          },
          "published_at": {
            "description": "When the comment was posted, RFC 3339 UTC. Where the platform shows only a relative time (\"3 weeks ago\"), the latest time that label allows (the fetch time minus the stated amount), listed in approximate_fields.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "text": {
            "description": "Comment body as plain text.",
            "type": "string"
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Permalink, when the platform has one.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "platform",
          "id",
          "post_id",
          "parent_id",
          "url",
          "text",
          "author",
          "published_at",
          "edited_at",
          "is_edited",
          "is_pinned",
          "is_liked_by_author",
          "is_by_post_author",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "CommentMetrics": {
        "properties": {
          "like_count": {
            "description": "Likes or upvotes; never negative.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "reply_count": {
            "description": "Direct replies.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "like_count",
          "reply_count"
        ],
        "type": "object"
      },
      "CommentPlatformSpecific": {
        "properties": {
          "bluesky": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BlueskyCommentSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "Bluesky's own reply fields."
          },
          "facebook": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookCommentSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "Facebook's own comment fields."
          },
          "instagram": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InstagramCommentSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "Instagram's own comment fields."
          },
          "reddit": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RedditCommentSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "Reddit's own comment fields."
          },
          "rumble": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RumbleCommentSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "Rumble's own comment fields."
          },
          "snapchat": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SnapchatCommentSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "Snapchat's own comment fields."
          },
          "threads": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ThreadsCommentSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "Threads' own reply fields."
          },
          "tiktok": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokCommentSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "TikTok's own comment fields."
          }
        },
        "type": "object"
      },
      "Community": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform or parsed from display text (\"762.0K members\": metrics.member_count). [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "avatar_url": {
            "description": "The community's icon or picture; null when it has none. Platform CDN URLs can expire.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "banner_url": {
            "description": "Header or cover image URL; null when it has none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "categories": {
            "description": "Topics or categories the platform files it under, as shown (not normalized); [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "created_at": {
            "description": "When it was created, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "description": "Its short description as plain text; null when it has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native community ID (string): Reddit's subreddit ID with its t5_ prefix, Facebook's numeric group ID.",
            "type": "string"
          },
          "is_nsfw": {
            "description": "Marked adult (NSFW) by the platform; null where the platform has no such mark.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/CommunityMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "moderators": {
            "description": "Accounts that run it (admins and moderators) the platform shows; [] when none are shown (listed in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "name": {
            "description": "The name its links use, without a prefix (golang for r/golang; a Facebook group's vanity name); null when it has none (a Facebook group known only by its number).",
            "type": [
              "string",
              "null"
            ]
          },
          "platform": {
            "description": "Platform ID (reddit, facebook, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/CommunityPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "privacy": {
            "description": "public: anyone can see its posts and any member can post; restricted: anyone can see its posts, only approved members can post; private: only members can see its posts (a private community answers private_or_unavailable unless its page shows these fields logged out). New values may be added; treat unknown values as restricted.",
            "enum": [
              "public",
              "restricted",
              "private",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "rules": {
            "description": "Its published rules, in the platform's order; [] when it has none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/CommunityRule"
            },
            "type": "array"
          },
          "title": {
            "description": "The community's title as its page shows it (\"The Go Programming Language\"; what Facebook calls a group's name); null when it has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Canonical community URL (https://www.reddit.com/r/golang/, https://www.facebook.com/groups/<id>/).",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "name",
          "title",
          "description",
          "url",
          "avatar_url",
          "banner_url",
          "privacy",
          "is_nsfw",
          "categories",
          "rules",
          "moderators",
          "created_at",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "CommunityMetrics": {
        "properties": {
          "member_count": {
            "description": "Members (on Reddit, subscribers) as the platform counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "member_count"
        ],
        "type": "object"
      },
      "CommunityPlatformSpecific": {
        "properties": {
          "facebook": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookCommunitySpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Facebook group's own fields."
          },
          "reddit": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RedditCommunitySpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A subreddit's own fields."
          },
          "x": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/XCommunitySpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An X Community's own fields."
          }
        },
        "type": "object"
      },
      "CommunityRule": {
        "properties": {
          "description": {
            "description": "Its explanation as plain text; null when it has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The rule's short title (Reddit short_name, Facebook rule_title).",
            "type": "string"
          }
        },
        "required": [
          "title",
          "description"
        ],
        "type": "object"
      },
      "CommunitySummary": {
        "properties": {
          "avatar_url": {
            "description": "The community's icon or picture; null until the result is filled.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "description": "Its description as the index's snippet quotes it (often cut short: see approximate_fields); null when it quotes none (a platform's generic page text is not one).",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native community ID; null until the result is filled.",
            "type": [
              "string",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/CommunityMetrics",
            "description": "Counts as the index's text states them (\"762K members\"; rounded, as old as the index's copy: see approximate_fields), or the platform's current ones once filled; null = not stated."
          },
          "name": {
            "description": "The name its links use, as the matched link names it (golang for r/golang, a Facebook group's vanity name); null when the link names it only by number.",
            "type": [
              "string",
              "null"
            ]
          },
          "privacy": {
            "description": "Who can see and post, as the index's text says (\"Public group\"); null when it does not. New values may be added; treat unknown values as restricted.",
            "enum": [
              "public",
              "restricted",
              "private",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The community's title as the index's title shows it; null when it shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Canonical community URL (equals the result's url).",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "title",
          "description",
          "url",
          "avatar_url",
          "privacy",
          "metrics"
        ],
        "type": "object"
      },
      "Download": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of estimated or rounded values (a size from bitrate × duration, a duration in whole seconds). [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "author": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "The posting account."
          },
          "duration_ms": {
            "description": "Length of the post's primary video or audio in milliseconds; null for photo posts.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "files": {
            "description": "The post's files by item_index, the sound last; each item's best first (a url, the item's own kind before its separate audio, no watermark, with sound, not a manifest, then resolution). At least one has a url.",
            "items": {
              "$ref": "#/components/schemas/DownloadFile"
            },
            "type": "array"
          },
          "id": {
            "description": "Platform-native ID of the post (equals post.id).",
            "type": "string"
          },
          "platform": {
            "description": "Platform ID (tiktok, instagram, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/DownloadPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "platform_type": {
            "description": "The platform's own product label, lowercase (reel, short, story, …), as post.platform_type.",
            "type": [
              "string",
              "null"
            ]
          },
          "published_at": {
            "description": "When the post went public, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "text": {
            "description": "Caption or body as plain text.",
            "type": [
              "string",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "Largest cover or poster image URL of the post (the first attachment's; each file's own is files[].thumbnail_url); CDN links can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "Headline (Reddit title, Facebook video title); null on caption-only platforms.",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "The post's content shape, as post.type. New values may be added; treat unknown values as other.",
            "enum": [
              "video",
              "image",
              "carousel",
              "audio"
            ],
            "type": "string"
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Canonical URL of the post.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "url",
          "type",
          "platform_type",
          "title",
          "text",
          "author",
          "published_at",
          "duration_ms",
          "thumbnail_url",
          "files",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "DownloadFile": {
        "properties": {
          "audio_codec": {
            "description": "Audio codec of the file's sound; null when it has none. New values may be added; treat unknown values as other.",
            "enum": [
              "aac",
              "opus",
              "mp3",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "bitrate_kbps": {
            "description": "Average bitrate in kbit/s (video and audio), rounded; null when unknown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "duration_ms": {
            "description": "Duration in milliseconds (video and audio); null for images and when unknown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "expires_at": {
            "description": "When url stops working, RFC 3339 UTC, read from its signature; null when unknown or it does not expire.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "frame_rate": {
            "description": "Frames per second (video and gif), to two decimals (an NTSC 30000/1001 is 29.97); null for images and audio and when unknown.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "height": {
            "description": "Height in pixels (images and video).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_video_only": {
            "description": "True: video without its sound, which is the audio file of the same item_index. False: it plays with its sound, or has none. Null for images and audio.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_watermarked": {
            "description": "The platform's logo or the author's handle is burned into the picture (TikTok's download file); false: the clean original. Null for audio.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "item_index": {
            "description": "0-based position of the file's attachment in display order (post.media[item_index]); null for the post's sound (a slideshow's soundtrack).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "mime_type": {
            "description": "IANA media type without parameters (video/mp4, image/jpeg, audio/mp4); application/vnd.apple.mpegurl (HLS) or application/dash+xml (DASH) for a streaming manifest.",
            "type": [
              "string",
              "null"
            ]
          },
          "size_bytes": {
            "description": "File size in bytes; an estimate from bitrate × duration is in approximate_fields.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "Cover image of this file's attachment (post.media[item_index].thumbnail_url), built like url; null for images and audio and when unknown.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "Kind of file, as media[].type. New values may be added; treat unknown values as other.",
            "enum": [
              "video",
              "image",
              "audio",
              "gif"
            ],
            "type": "string"
          },
          "url": {
            "description": "Direct CDN file URL, fetchable without cookies or headers; null when the platform serves it only with its cookie or to the IP that asked.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "video_codec": {
            "description": "Video codec (h264 plays everywhere; h265, vp9 and av1 need newer players); null for images and audio. New values may be added; treat unknown values as other.",
            "enum": [
              "h264",
              "h265",
              "vp9",
              "av1",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "width": {
            "description": "Width in pixels (images and video).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "item_index",
          "type",
          "url",
          "expires_at",
          "mime_type",
          "size_bytes",
          "width",
          "height",
          "duration_ms",
          "bitrate_kbps",
          "frame_rate",
          "video_codec",
          "audio_codec",
          "is_watermarked",
          "is_video_only",
          "thumbnail_url"
        ],
        "type": "object"
      },
      "DownloadPlatformSpecific": {
        "properties": {
          "tiktok": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokDownloadSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A TikTok download's own fields."
          }
        },
        "type": "object"
      },
      "Effect": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform or parsed from display text (e.g. metrics.post_count from \"304.5M videos\"). A list path (media) means the list may be incomplete. [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "creator": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "The account that made the effect. Fields are null where the platform names no account (TikTok's own effects show only a display name)."
          },
          "description": {
            "description": "The creator's description of the effect; null when empty or not exposed.",
            "type": [
              "string",
              "null"
            ]
          },
          "icon_url": {
            "description": "The effect's icon image URL. Platform CDN URLs can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native effect ID (string; TikTok's effect ID, the number ending its /effect/ link).",
            "type": "string"
          },
          "is_official": {
            "description": "True when the platform itself made the effect, false for an effect made by a community creator; null when not exposed.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "media": {
            "description": "Preview images and videos the platform shows of the effect in use; [] if none or not exposed.",
            "items": {
              "$ref": "#/components/schemas/Media"
            },
            "type": "array"
          },
          "metrics": {
            "$ref": "#/components/schemas/EffectMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "name": {
            "description": "The effect's name as the platform shows it.",
            "type": "string"
          },
          "platform": {
            "description": "Platform ID (tiktok, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/EffectPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "published_at": {
            "description": "When the effect was published, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Canonical public page of the effect.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "url",
          "name",
          "description",
          "creator",
          "is_official",
          "icon_url",
          "media",
          "published_at",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "EffectMetrics": {
        "properties": {
          "post_count": {
            "description": "Public posts made with the effect, as the platform counts them (TikTok's \"videos\" figure on the effect page).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "total_view_count": {
            "description": "Views across all posts made with the effect.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "post_count",
          "total_view_count"
        ],
        "type": "object"
      },
      "EffectPlatformSpecific": {
        "properties": {
          "tiktok": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokEffectSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A TikTok effect's own fields."
          }
        },
        "type": "object"
      },
      "Embed": {
        "properties": {
          "author": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "The account the embedded item belongs to: the post's author, the playlist's owner, or for a profile the account itself."
          },
          "embed_url": {
            "description": "The platform's embed page alone, for an iframe's src (what html's script loads); null when the platform has none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "height": {
            "description": "Height in pixels; null when the embed sizes itself to its content (Instagram's always do).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "html": {
            "description": "The platform's embed code, ready to paste into an HTML page: its markup and, unless asked to leave it out, the script tag that turns it into the embedded post or profile. It loads the platform's script and content in the visitor's browser.",
            "type": "string"
          },
          "id": {
            "description": "The ID the platform's embed is addressed by (as in embed_url): a post's ID (equals post.id), a playlist's ID, and for a profile the account's username on platforms whose profile embeds are addressed by it (Instagram, TikTok); the account's numeric ID, when known, is author.id.",
            "type": "string"
          },
          "platform": {
            "description": "Platform ID (instagram, youtube, tiktok, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/EmbedPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "thumbnail_height": {
            "description": "Height of thumbnail_url in pixels; null when unknown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "Preview image URL the platform names for the embed (a post's image or cover, a profile's picture); platform CDN URLs can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "thumbnail_width": {
            "description": "Width of thumbnail_url in pixels; null when unknown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "title": {
            "description": "The title the platform gives the embed: a post's caption or a video's title, a profile's page title; null when it has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "What is embedded, named by its resource: post (any post: photo, carousel, video, reel), profile (an account), or playlist. New values may be added; treat unknown values as other.",
            "enum": [
              "post",
              "profile",
              "playlist"
            ],
            "type": "string"
          },
          "url": {
            "description": "Canonical public URL of what is embedded (post.url, profile.url): the link the embed opens.",
            "format": "uri",
            "type": "string"
          },
          "width": {
            "description": "Width in pixels the embed is laid out for (its maximum when it is responsive); null when the platform does not say.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "platform",
          "type",
          "id",
          "url",
          "html",
          "embed_url",
          "width",
          "height",
          "title",
          "author",
          "thumbnail_url",
          "thumbnail_width",
          "thumbnail_height",
          "platform_specific"
        ],
        "type": "object"
      },
      "EmbedPlatformSpecific": {
        "type": "object"
      },
      "Engagement": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of figures computed from an approximate input (a rounded follower or view count, a relative publish time); a posts[] path means at least one post's. [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "bottom_post_id": {
            "description": "ID of the rated post with the fewest interactions; the first on a tie.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native account ID (equals profile.id).",
            "type": "string"
          },
          "metrics": {
            "$ref": "#/components/schemas/EngagementMetrics",
            "description": "Figures over the counted posts (by the account, not pinned); each null when no counted post has its inputs."
          },
          "newest_post_at": {
            "description": "Publish time of the newest counted post, RFC 3339 UTC: when the account last posted.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "oldest_post_at": {
            "description": "Publish time of the oldest counted post, RFC 3339 UTC: where the sample starts.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "platform": {
            "description": "Platform ID (tiktok, instagram, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/EngagementPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "posts": {
            "description": "The sampled recent posts in the profile's order, each with its own figures. [] when none; [] and in unknown_fields when unreadable (a private account, a failed posts request).",
            "items": {
              "$ref": "#/components/schemas/EngagementPost"
            },
            "type": "array"
          },
          "profile": {
            "$ref": "#/components/schemas/Profile",
            "description": "The account, as its profile endpoint returns it; its metrics.follower_count divides every engagement_rate."
          },
          "top_post_id": {
            "description": "ID of the rated post with the most interactions (likes + comments); the first on a tie.",
            "type": [
              "string",
              "null"
            ]
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (posts, metrics.formats). [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Canonical profile URL (equals profile.url).",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "url",
          "profile",
          "posts",
          "metrics",
          "oldest_post_at",
          "newest_post_at",
          "top_post_id",
          "bottom_post_id",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "EngagementFormat": {
        "properties": {
          "counted_post_count": {
            "description": "Counted posts of this type.",
            "format": "int64",
            "type": "integer"
          },
          "engagement_rate": {
            "description": "Mean engagement_rate of the rated posts of this type.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "interactions_per_post": {
            "description": "Mean interactions per rated post of this type.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "type": {
            "description": "Post type (post.type). New values may be added; treat unknown values as other.",
            "enum": [
              "video",
              "image",
              "carousel",
              "text",
              "link",
              "audio"
            ],
            "type": "string"
          },
          "views_per_post": {
            "description": "Mean views per post of this type.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "type",
          "counted_post_count",
          "views_per_post",
          "interactions_per_post",
          "engagement_rate"
        ],
        "type": "object"
      },
      "EngagementMetrics": {
        "properties": {
          "comment_to_like_ratio": {
            "description": "The rated posts' comments over their likes.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "comments_per_post": {
            "description": "Mean comments per counted post with a comment count.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "counted_post_count": {
            "description": "Sampled posts that enter the figures.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "engagement_rate": {
            "description": "Mean of the rated posts' engagement_rate (interactions per follower), as a fraction (0.042 = 4.2%).",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "engagement_rate_stddev": {
            "description": "Population standard deviation of the rated posts' engagement_rate: how uneven they perform. Null under 2 rated posts.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "formats": {
            "description": "The counted posts by post type, most posts first; [] when none are counted.",
            "items": {
              "$ref": "#/components/schemas/EngagementFormat"
            },
            "type": "array"
          },
          "interactions_per_post": {
            "description": "Mean interactions (likes + comments) per rated post; known without a follower count.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "likes_per_post": {
            "description": "Mean likes per counted post with a like count.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "median_engagement_rate": {
            "description": "Median of the rated posts' engagement_rate.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "median_views_per_post": {
            "description": "Median views per counted post: the typical post, unmoved by one viral hit.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "posts_per_week": {
            "description": "Posting cadence: intervals between counted posts per week from oldest_post_at to newest_post_at.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "quotes_per_post": {
            "description": "Mean quote posts per counted post with a quote count.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "rated_post_count": {
            "description": "Counted posts with known like and comment counts: what interaction figures and rates are over.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "reposts_per_post": {
            "description": "Mean reposts per counted post with a repost count.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "sampled_post_count": {
            "description": "Posts in the sample, the length of posts; null when unreadable.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "saves_per_post": {
            "description": "Mean saves per counted post with a save count.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "shares_per_post": {
            "description": "Mean shares per counted post with a share count.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "view_engagement_rate": {
            "description": "Mean of the rated posts' view_engagement_rate (interactions per view), as a fraction.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "views_per_post": {
            "description": "Mean views per counted post with a view count.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "sampled_post_count",
          "counted_post_count",
          "rated_post_count",
          "views_per_post",
          "median_views_per_post",
          "likes_per_post",
          "comments_per_post",
          "shares_per_post",
          "reposts_per_post",
          "quotes_per_post",
          "saves_per_post",
          "interactions_per_post",
          "engagement_rate",
          "median_engagement_rate",
          "engagement_rate_stddev",
          "view_engagement_rate",
          "comment_to_like_ratio",
          "posts_per_week",
          "formats"
        ],
        "type": "object"
      },
      "EngagementPlatformSpecific": {
        "type": "object"
      },
      "EngagementPost": {
        "properties": {
          "engagement_rate": {
            "description": "Interactions (likes + comments) per follower, as a fraction (0.042 = 4.2%); can exceed 1. Null when a count is unknown or there are no followers.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "engagement_vs_median": {
            "description": "Interactions over the rated posts' median: 1 is typical for the account, 3 three times typical.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "is_counted": {
            "description": "True when the post enters the figures: by the account itself and not pinned.",
            "type": "boolean"
          },
          "post": {
            "$ref": "#/components/schemas/Post",
            "description": "The post, as the platform's posts endpoint returns it."
          },
          "view_engagement_rate": {
            "description": "Interactions (likes + comments) per view, as a fraction. Null when a count is unknown or there are no views.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "views_vs_median": {
            "description": "Views over metrics.median_views_per_post: 1 is typical, 3 three times typical.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "post",
          "is_counted",
          "engagement_rate",
          "view_engagement_rate",
          "engagement_vs_median",
          "views_vs_median"
        ],
        "type": "object"
      },
      "ErrorBody": {
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorDetail"
          }
        },
        "required": [
          "error"
        ],
        "type": "object"
      },
      "ErrorDetail": {
        "properties": {
          "charged": {
            "description": "Whether the request was charged: always false, failed requests are free.",
            "type": "boolean"
          },
          "code": {
            "description": "Machine-readable error code (see the error codes list); stable.",
            "enum": [
              "invalid_input",
              "invalid_cursor",
              "unauthorized",
              "forbidden",
              "insufficient_credits",
              "spend_limit_reached",
              "rate_limited",
              "request_too_large",
              "method_not_allowed",
              "endpoint_retired",
              "idempotency_key_reused",
              "idempotency_key_in_progress",
              "job_not_found",
              "unknown_endpoint",
              "not_found",
              "private_or_unavailable",
              "no_transcript",
              "no_live",
              "no_media",
              "upstream_blocked",
              "upstream_error",
              "overloaded",
              "internal"
            ],
            "type": "string"
          },
          "details": {
            "description": "The code's dynamic values (the error codes list documents each code's keys); {} when none.",
            "type": "object"
          },
          "doc_url": {
            "description": "URL of this code's documentation.",
            "type": "string"
          },
          "message": {
            "description": "What went wrong and how to fix it, for humans and agents; wording may change.",
            "type": "string"
          },
          "param": {
            "description": "The query parameter or header the error is about; null when it is not about one input.",
            "type": [
              "string",
              "null"
            ]
          },
          "remediation": {
            "description": "What to do about this code, one sentence.",
            "type": "string"
          },
          "request_id": {
            "description": "Unique request ID; include it when contacting support.",
            "type": "string"
          },
          "retryable": {
            "description": "True when repeating the same request later may succeed (after details.retry_after when present).",
            "type": "boolean"
          },
          "status": {
            "description": "The HTTP status of the response, repeated for clients that only see the body.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "code",
          "message",
          "request_id",
          "status",
          "retryable",
          "param",
          "remediation",
          "doc_url",
          "details",
          "charged"
        ],
        "type": "object"
      },
      "EventMetrics": {
        "properties": {
          "attendee_count": {
            "description": "People who said they are going (after the event: who went), as the platform counts them; null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "attendee_count"
        ],
        "type": "object"
      },
      "EventPlatformSpecific": {
        "properties": {
          "facebook": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookEventSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Facebook event's own fields."
          }
        },
        "type": "object"
      },
      "FacebookAdAgeGenderReach": {
        "properties": {
          "age_range": {
            "description": "The age range (18-24, 65+).",
            "type": "string"
          },
          "female": {
            "description": "Women reached; null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "male": {
            "description": "Men reached; null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "unknown": {
            "description": "Accounts of unknown gender reached; null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "age_range",
          "male",
          "female",
          "unknown"
        ],
        "type": "object"
      },
      "FacebookAdAgeGenderShare": {
        "properties": {
          "age_range": {
            "description": "The age range (18-24, 65+).",
            "type": "string"
          },
          "female": {
            "description": "Share among women (0 to 1); null when not shown.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "male": {
            "description": "Share among men (0 to 1); null when not shown.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "unknown": {
            "description": "Share among people of unknown gender (0 to 1); null when not shown.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "age_range",
          "male",
          "female",
          "unknown"
        ],
        "type": "object"
      },
      "FacebookAdCountryReach": {
        "properties": {
          "ages": {
            "description": "Unique accounts reached there per age range.",
            "items": {
              "$ref": "#/components/schemas/FacebookAdAgeGenderReach"
            },
            "type": "array"
          },
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country code.",
            "type": "string"
          }
        },
        "required": [
          "country_code",
          "ages"
        ],
        "type": "object"
      },
      "FacebookAdImpressionShares": {
        "properties": {
          "by_age_gender": {
            "description": "Share of impressions per age range, by gender (0 to 1).",
            "items": {
              "$ref": "#/components/schemas/FacebookAdAgeGenderShare"
            },
            "type": "array"
          },
          "by_region": {
            "description": "Share of impressions per region (0 to 1).",
            "items": {
              "$ref": "#/components/schemas/FacebookAdRegionShare"
            },
            "type": "array"
          }
        },
        "required": [
          "by_age_gender",
          "by_region"
        ],
        "type": "object"
      },
      "FacebookAdLocation": {
        "properties": {
          "is_excluded": {
            "description": "The advertiser excluded the place rather than targeting it.",
            "type": "boolean"
          },
          "name": {
            "description": "The place as Meta names it (United Kingdom, Berlin).",
            "type": "string"
          },
          "type": {
            "description": "The kind of place (countries, regions, cities); null when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "type",
          "is_excluded"
        ],
        "type": "object"
      },
      "FacebookAdRegionShare": {
        "properties": {
          "region": {
            "description": "The region as Meta names it (California).",
            "type": "string"
          },
          "share": {
            "description": "Its share (0 to 1); null when not shown.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "region",
          "share"
        ],
        "type": "object"
      },
      "FacebookAdResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Ad"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "FacebookAdSpecific": {
        "properties": {
          "advertiser_categories": {
            "description": "The advertiser page's categories (Wine/spirits); [] when not shown (in unknown_fields when not shown).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "advertiser_instagram": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The advertiser's Instagram account, when Meta links one; null otherwise or outside the ad's details."
          },
          "advertiser_instagram_follower_count": {
            "description": "Followers of the advertiser's Instagram account; null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "advertiser_like_count": {
            "description": "The advertiser's page likes; null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "beneficiary": {
            "description": "Whom the ad benefits, as disclosed for ads shown in the EU; null when not disclosed.",
            "type": [
              "string",
              "null"
            ]
          },
          "collation_count": {
            "description": "How many ads share this creative and text; null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "collation_id": {
            "description": "The group of ads that share this creative and text; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "cta_type": {
            "description": "The call to action's type (shop_now, learn_more), whatever language cta_text is in; null when the ad has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "impression_shares": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookAdImpressionShares"
              },
              {
                "type": "null"
              }
            ],
            "description": "A political or social-issue ad's audience: its share of impressions by age and gender and by region; null for other ads."
          },
          "is_advertiser_deleted": {
            "description": "The advertiser's page has since been deleted; null when not shown.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_removed": {
            "description": "Meta took the ad down for breaking its standards; null when not shown.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_synthetic": {
            "description": "The advertiser disclosed digitally created or altered media (an AI disclosure); null when not shown.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "link_caption": {
            "description": "The link caption shown under the creative (usually the destination's domain); null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "partner": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The creator whose post a branded content ad promotes for the advertiser; null for other ads."
          },
          "removal_reasons": {
            "description": "Meta's reasons for taking it down; [] when none (in unknown_fields when not shown).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "special_ad_categories": {
            "description": "Meta's special ad categories the ad is filed under (political, housing, employment, credit); [] for an ordinary ad.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "targeting": {
            "description": "Whom the advertiser targeted and whom the ad reached, per region that discloses it (the EU, the UK); [] when not disclosed (in unknown_fields when not shown).",
            "items": {
              "$ref": "#/components/schemas/FacebookAdTargeting"
            },
            "type": "array"
          }
        },
        "required": [
          "cta_type",
          "link_caption",
          "special_ad_categories",
          "collation_id",
          "collation_count",
          "partner",
          "advertiser_like_count",
          "advertiser_categories",
          "is_advertiser_deleted",
          "advertiser_instagram",
          "advertiser_instagram_follower_count",
          "beneficiary",
          "is_synthetic",
          "is_removed",
          "removal_reasons",
          "targeting",
          "impression_shares"
        ],
        "type": "object"
      },
      "FacebookAdTargeting": {
        "properties": {
          "age_max": {
            "description": "Oldest age targeted (65 means 65 and over); null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "age_min": {
            "description": "Youngest age targeted; null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "genders": {
            "description": "Genders targeted (female, male); [] when all.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "locations": {
            "description": "Places the advertiser targeted or excluded; [] when not shown.",
            "items": {
              "$ref": "#/components/schemas/FacebookAdLocation"
            },
            "type": "array"
          },
          "reach": {
            "description": "Unique accounts the ad reached in the region; null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "reach_by_country": {
            "description": "Unique accounts reached per country, by age range and gender; [] when not shown.",
            "items": {
              "$ref": "#/components/schemas/FacebookAdCountryReach"
            },
            "type": "array"
          },
          "region": {
            "description": "The disclosing region. New values may be added.",
            "enum": [
              "eu",
              "uk"
            ],
            "type": "string"
          }
        },
        "required": [
          "region",
          "reach",
          "genders",
          "age_min",
          "age_max",
          "locations",
          "reach_by_country"
        ],
        "type": "object"
      },
      "FacebookAd_transcriptResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Transcript"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "FacebookAdminCountry": {
        "properties": {
          "count": {
            "description": "How many of the Page's admins are there.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "country": {
            "description": "The country's name.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "country",
          "count"
        ],
        "type": "object"
      },
      "FacebookAdsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 10), most recently started first, in Meta's recency groups with sort=newest, most impressions first with sort=popular.",
            "items": {
              "$ref": "#/components/schemas/Ad"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookBusinessDay": {
        "properties": {
          "day": {
            "description": "The day of the week, as Facebook names it (Monday).",
            "type": [
              "string",
              "null"
            ]
          },
          "hours": {
            "description": "The day's hours as shown, such as 11:00 AM - 2:30 PM, 4:30 PM - 9:30 PM, or Closed.",
            "type": [
              "string",
              "null"
            ]
          },
          "periods": {
            "description": "The same hours as 24-hour times, one per opening; [] on a closed day or when the text is not a list of times.",
            "items": {
              "$ref": "#/components/schemas/FacebookBusinessPeriod"
            },
            "type": "array"
          }
        },
        "required": [
          "day",
          "hours",
          "periods"
        ],
        "type": "object"
      },
      "FacebookBusinessPeriod": {
        "properties": {
          "close": {
            "description": "Closing time, 24-hour HH:MM, local to the business.",
            "type": "string"
          },
          "open": {
            "description": "Opening time, 24-hour HH:MM, local to the business.",
            "type": "string"
          }
        },
        "required": [
          "open",
          "close"
        ],
        "type": "object"
      },
      "FacebookCommentSpecific": {
        "properties": {
          "author_gender": {
            "description": "The commenter's gender as Facebook states it to logged-out visitors; null when it states none (Pages, most accounts that chose not to). New values may be added.",
            "enum": [
              "male",
              "female",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "image_url": {
            "description": "The photo the comment attaches, on Facebook's CDN (signed, expires within days); null when it attaches none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "reactions": {
            "description": "Reactions by type, most first, as Facebook lists them under the comment; [] when none.",
            "items": {
              "$ref": "#/components/schemas/FacebookReaction"
            },
            "type": "array"
          }
        },
        "required": [
          "reactions",
          "author_gender",
          "image_url"
        ],
        "type": "object"
      },
      "FacebookCommentsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 10), newest first with sort=newest, Facebook's All comments view: every top-level comment, the most relevant first with sort=relevance.",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookCommunitySpecific": {
        "properties": {
          "admin_count": {
            "description": "Administrators of the group.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "admin_ids": {
            "description": "The IDs of the administrators among moderators (the rest are its moderators), as far as Facebook shows them; [] when none are shown (listed in unknown_fields when the source cannot see them).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "daily_post_count": {
            "description": "Posts in the group in the last day, as Facebook counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "history_summary": {
            "description": "Facebook's summary of the group's history (created, name changes), as shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_visible": {
            "description": "True when anyone can find the group in search (Facebook's Visible), false when only members can (Hidden).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "locations": {
            "description": "The places the group's admins tie it to, as shown; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "moderator_count": {
            "description": "Moderators of the group (not counting its administrators).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "monthly_post_count": {
            "description": "Posts in the group in the last month, as Facebook counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "owner": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The Page or account the group is shown as belonging to (Facebook's \"Group by ...\" on its cover); null when Facebook names none."
          },
          "weekly_new_member_count": {
            "description": "Members who joined in the last week (parsed from Facebook's text).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "daily_post_count",
          "monthly_post_count",
          "weekly_new_member_count",
          "admin_count",
          "admin_ids",
          "moderator_count",
          "is_visible",
          "history_summary",
          "owner",
          "locations"
        ],
        "type": "object"
      },
      "FacebookEngagementResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Engagement"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "FacebookEventMetrics": {
        "properties": {
          "interested_count": {
            "description": "People who marked themselves interested (not going), as Facebook counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "response_count": {
            "description": "People who responded going or interested, together, as Facebook counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "interested_count",
          "response_count"
        ],
        "type": "object"
      },
      "FacebookEventResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ScheduledEvent",
            "description": "In Facebook's words: `metrics.attendee_count` is going."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "FacebookEventSpecific": {
        "properties": {
          "city_id": {
            "description": "ID of the city Facebook files it under (its city Page, the number in facebook.com/events/explore/<city>/<id>/, which lists that city's events); place.city is the city's name. Null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "date_text": {
            "description": "When it happens, as Facebook shows it, in the event's own time zone (\"Sun, Nov 8 at 3:00 PM EST and 7 more\", \"Sat, Nov 21 - Nov 22\", \"Happening now\"): on a recurring event its next date, where start_at is its first. Display text in the viewer's language; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "frequency": {
            "description": "How often it repeats, as Facebook names it, lowercased (single for a one-off event); null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/FacebookEventMetrics",
            "description": "Facebook's own counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "occurrence_count": {
            "description": "Dates of its recurring series (the parent's child events); 0 for a single event.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "price_text": {
            "description": "The ticket price or range as Facebook shows it (\"$25 – $40\", \"Free\"); null when none is shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "ticket_provider": {
            "description": "Who sells the tickets ticket_url links to (Ticketmaster, Eventbrite), as Facebook names it; null when none.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "ticket_provider",
          "price_text",
          "date_text",
          "frequency",
          "occurrence_count",
          "city_id",
          "metrics"
        ],
        "type": "object"
      },
      "FacebookEventsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 8), oldest first. In Facebook's words: `metrics.attendee_count` is going.",
            "items": {
              "$ref": "#/components/schemas/ScheduledEvent"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookGroupResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Community"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "FacebookGroup_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 3), the group's items for sale, newest first by when each entered the group's feed with sort=listings, Facebook's New posts: newest first by when a post entered the group's feed with sort=newest, the posts most recently commented on or reacted to first with sort=recent_activity, Facebook's Most relevant ranking of the group's posts with sort=relevance.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookLink": {
        "properties": {
          "image_url": {
            "description": "The card's image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The card's headline.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The linked page, as the author shared it (Facebook's l.facebook.com redirect removed).",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "url",
          "title",
          "image_url"
        ],
        "type": "object"
      },
      "FacebookListingResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Product"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "FacebookNameChange": {
        "properties": {
          "changed_at": {
            "description": "When it changed, RFC 3339 UTC.",
            "format": "date-time",
            "type": "string"
          },
          "name": {
            "description": "The name it took.",
            "type": "string"
          }
        },
        "required": [
          "name",
          "changed_at"
        ],
        "type": "object"
      },
      "FacebookPhotosResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 8), Newest first, as the Photos tab shows them.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookPlaceSpecific": {
        "properties": {
          "checkin_count": {
            "description": "People who checked in at the place, as Facebook shows it; null when Facebook shows no count (it shows none for a city).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "checkin_count"
        ],
        "type": "object"
      },
      "FacebookPlace_eventsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 12), Facebook's ranking of the city's events, not by date. In Facebook's words: `metrics.attendee_count` is going.",
            "items": {
              "$ref": "#/components/schemas/ScheduledEvent"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookPostGroup": {
        "properties": {
          "id": {
            "description": "The group's numeric ID.",
            "type": "string"
          },
          "name": {
            "description": "The group's name, as its page shows it.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The group's URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "url"
        ],
        "type": "object"
      },
      "FacebookPostListing": {
        "properties": {
          "id": {
            "description": "The listing's ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_sold": {
            "description": "Marked sold.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "location": {
            "description": "Where it is, as Facebook shows it.",
            "type": [
              "string",
              "null"
            ]
          },
          "price_text": {
            "description": "Its price as Facebook shows it (BDT14,000, FREE).",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The item's name.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The item's Marketplace page (facebook.com/marketplace/item/<id>), which facebook.listing reads; null for an item listed only in the group.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "price_text",
          "location",
          "is_sold",
          "url"
        ],
        "type": "object"
      },
      "FacebookPostMusic": {
        "properties": {
          "id": {
            "description": "Facebook's ID of the sound.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_original": {
            "description": "The creator's own audio (false: a track from Facebook's library).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "title": {
            "description": "The sound's title as the reel shows it (\"National Geographic · Original audio\" for a creator's own).",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "is_original"
        ],
        "type": "object"
      },
      "FacebookPostResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "FacebookPostSpecific": {
        "properties": {
          "feedback_id": {
            "description": "Facebook's feedback ID of the post: the thread its comments and reactions hang on.",
            "type": [
              "string",
              "null"
            ]
          },
          "group": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookPostGroup"
              },
              {
                "type": "null"
              }
            ],
            "description": "The group the post was published in; null when it is not a group's post."
          },
          "is_attachment_unavailable": {
            "description": "What the post attached is gone: Facebook shows it as unavailable or empty, so the post can have no text and no media. Null when the page does not say.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "link": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookLink"
              },
              {
                "type": "null"
              }
            ],
            "description": "The link card a post shares (an article, a site, an event); null when none."
          },
          "listing": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookPostListing"
              },
              {
                "type": "null"
              }
            ],
            "description": "The item for sale a group's post lists; null when it lists none, or none any more (a listing taken down: see is_attachment_unavailable)."
          },
          "music": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookPostMusic"
              },
              {
                "type": "null"
              }
            ],
            "description": "The sound a reel credits; null when the post credits none, or the endpoint can't see it."
          },
          "reactions": {
            "description": "Reactions by type, most first, as Facebook lists them under the post; [] when none.",
            "items": {
              "$ref": "#/components/schemas/FacebookReaction"
            },
            "type": "array"
          },
          "shared_post": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookSharedPost"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post this one reshares; null when it is not a reshare."
          },
          "video_id": {
            "description": "The video's ID (facebook.com/reel/<video_id>) on a video or reel post; null on other posts.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "feedback_id",
          "video_id",
          "reactions",
          "shared_post",
          "link",
          "music",
          "group",
          "listing",
          "is_attachment_unavailable"
        ],
        "type": "object"
      },
      "FacebookPostsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 3), newest first.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookProductSpecific": {
        "properties": {
          "delivery_types": {
            "description": "How the item changes hands, as Marketplace lists it: in_person (local pickup), shipping, door_pickup, door_dropoff, public_meetup. [] when not shown (listed in unknown_fields). New values may be added.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "is_buy_now_enabled": {
            "description": "The item can be bought on Facebook with Marketplace checkout (Buy now); false: the buyer arranges payment with the seller.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_local_pickup": {
            "description": "The buyer can pick it up from the seller in person.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "latitude": {
            "description": "WGS 84 latitude of the listing's area in degrees (Facebook shows an area, not the seller's address: always listed in approximate_fields); set together with longitude.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "location": {
            "description": "Where the item is (a city or area, Austin, TX), as Marketplace shows it; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "location_id": {
            "description": "Marketplace's ID of the city the item is in: a Marketplace search takes it as its location; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "longitude": {
            "description": "WGS 84 longitude of the listing's area in degrees (always listed in approximate_fields); set together with latitude.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "postal_code": {
            "description": "Postal code of the listing's area, as Marketplace shows it (homes and rentals); null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "price_period": {
            "description": "The period price pays for: month for a property rental's monthly rent (Marketplace shows $914 / Month); null for a sale price. New values may be added.",
            "enum": [
              "month",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "published_at": {
            "description": "When it was listed, RFC 3339 UTC; null when not shown.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "seller_joined_at": {
            "description": "When the seller joined Facebook, RFC 3339 UTC; null when not shown.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "seller_rating": {
            "description": "The seller's average Marketplace rating as a seller, 1 to 5 stars; null when the seller's ratings are private or there are none.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "seller_rating_count": {
            "description": "Ratings behind seller_rating; null when the seller's ratings are private.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "location",
          "location_id",
          "published_at",
          "is_local_pickup",
          "latitude",
          "longitude",
          "delivery_types",
          "is_buy_now_enabled",
          "seller_rating",
          "seller_rating_count",
          "price_period",
          "postal_code",
          "seller_joined_at"
        ],
        "type": "object"
      },
      "FacebookProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "FacebookProfileSpecific": {
        "properties": {
          "ad_library_entity_type": {
            "description": "Meta's own label for the advertiser in its Ad Library, as written there (PERSON_PROFILE, REGULAR_PAGE, IG_ADS_IDENTITY for an advertiser that exists only on Instagram). It labels brands PERSON_PROFILE too: it says how Meta files the advertiser, not what it is. New values may appear. Null for a profile read from elsewhere.",
            "type": [
              "string",
              "null"
            ]
          },
          "admin_countries": {
            "description": "Where the people who manage the Page are, as Page transparency counts them. [] when it shows none.",
            "items": {
              "$ref": "#/components/schemas/FacebookAdminCountry"
            },
            "type": "array"
          },
          "alternate_name": {
            "description": "The other name the account shows beside its name.",
            "type": [
              "string",
              "null"
            ]
          },
          "business_hours": {
            "description": "A business's weekly opening hours, a day at a time. [] when it shows none.",
            "items": {
              "$ref": "#/components/schemas/FacebookBusinessDay"
            },
            "type": "array"
          },
          "education": {
            "description": "The schools a person's intro lists, as written there. [] when it lists none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "email": {
            "description": "The public contact email the profile shows.",
            "type": [
              "string",
              "null"
            ]
          },
          "gender": {
            "description": "A person's gender as Facebook states it, male or female; null for a Page or when it states none.",
            "type": [
              "string",
              "null"
            ]
          },
          "hometown": {
            "description": "The hometown a person's intro states.",
            "type": [
              "string",
              "null"
            ]
          },
          "hours_status": {
            "description": "Whether the business is open at fetch time, in Facebook's words (Open now, Closed now, Closing soon).",
            "type": [
              "string",
              "null"
            ]
          },
          "instagram_follower_count": {
            "description": "That Instagram account's exact followers, as the Ad Library's advertiser search shows them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "instagram_username": {
            "description": "The Instagram account Meta links to the advertiser, as its Ad Library's advertiser search shows it; null when it links none or for a profile read from elsewhere.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_deleted": {
            "description": "True when the Page has been deleted, as the Ad Library's advertiser search states it: its ads stay in the library. Null for a profile read from elsewhere.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_instagram_verified": {
            "description": "Whether that Instagram account has the verified badge, as the Ad Library's advertiser search shows it.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_memorialized": {
            "description": "True for a memorialized account (\"Remembering …\").",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_political_advertiser": {
            "description": "True when the account has run ads about social issues, elections or politics.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_running_ads": {
            "description": "True when the account is running ads now (Page transparency).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "name_changes": {
            "description": "The Page's earlier name changes, newest first. [] when it has none.",
            "items": {
              "$ref": "#/components/schemas/FacebookNameChange"
            },
            "type": "array"
          },
          "owner_location": {
            "description": "The confirmed owner's location, as Page transparency states it.",
            "type": [
              "string",
              "null"
            ]
          },
          "owner_name": {
            "description": "The organization or person Facebook confirms is responsible for the Page.",
            "type": [
              "string",
              "null"
            ]
          },
          "page_id": {
            "description": "The Page ID Facebook shows under Page transparency, which is also the advertiser's ID in Meta's Ad Library; null for an account without one (most people's profiles).",
            "type": [
              "string",
              "null"
            ]
          },
          "phone": {
            "description": "The public contact phone number the profile shows, as written there.",
            "type": [
              "string",
              "null"
            ]
          },
          "price_range": {
            "description": "A business's price range as shown, such as $$.",
            "type": [
              "string",
              "null"
            ]
          },
          "rating": {
            "description": "The rating line as shown, such as 96% recommend (1,121 reviews).",
            "type": [
              "string",
              "null"
            ]
          },
          "recommend_percent": {
            "description": "The share of reviewers who recommend the Page, as a percentage; null when it is not yet rated.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "relationship": {
            "description": "The relationship a person's intro states, as written there.",
            "type": [
              "string",
              "null"
            ]
          },
          "review_count": {
            "description": "How many reviews the Page has.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "services": {
            "description": "What the business offers, as Facebook lists it (Delivery, Takeout, Dine-in). [] when it lists none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "talking_about_count": {
            "description": "How many people Facebook counts as talking about the account. It is shown only on the profile's own page, which most requests are answered without: null when this answer did not read it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "were_here_count": {
            "description": "How many people have checked in at a place's Page. It is shown only on the profile's own page, which most requests are answered without: null when this answer did not read it, or for an account that is not a place.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "work": {
            "description": "The jobs a person's intro lists, as written there (Founder and CEO at Meta). [] when it lists none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "page_id",
          "gender",
          "alternate_name",
          "is_memorialized",
          "talking_about_count",
          "were_here_count",
          "email",
          "phone",
          "price_range",
          "rating",
          "recommend_percent",
          "review_count",
          "services",
          "hours_status",
          "business_hours",
          "work",
          "education",
          "hometown",
          "relationship",
          "owner_name",
          "owner_location",
          "is_running_ads",
          "is_political_advertiser",
          "admin_countries",
          "name_changes",
          "instagram_username",
          "instagram_follower_count",
          "is_instagram_verified",
          "is_deleted",
          "ad_library_entity_type"
        ],
        "type": "object"
      },
      "FacebookReaction": {
        "properties": {
          "count": {
            "description": "How many people reacted with it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "type": {
            "description": "Reaction type. New values may be added.",
            "enum": [
              "like",
              "love",
              "care",
              "haha",
              "wow",
              "sad",
              "angry"
            ],
            "type": "string"
          }
        },
        "required": [
          "type",
          "count"
        ],
        "type": "object"
      },
      "FacebookReelsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 10), newest first.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookRepliesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 10), oldest first.",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookSearch_adsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 10), most impressions first.",
            "items": {
              "$ref": "#/components/schemas/Ad"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookSearch_advertisersResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 15), the search box's own order.",
            "items": {
              "$ref": "#/components/schemas/Profile"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookSearch_eventsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 20), Facebook's ranking of the results, not by date. In Facebook's words: `metrics.attendee_count` is going.",
            "items": {
              "$ref": "#/components/schemas/ScheduledEvent"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookSearch_groupsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookSearch_listingsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 30), the closest to the place first with sort=nearest, the latest listed first, by the day: later pages can hold newer listings with sort=newest, the lowest price first with sort=price_asc, the highest price first with sort=price_desc, Marketplace's Suggested order with sort=relevance.",
            "items": {
              "$ref": "#/components/schemas/Product"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookSearch_placesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 10), most relevant first, as Marketplace's location picker ranks them.",
            "items": {
              "$ref": "#/components/schemas/Place"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookSearch_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookSearch_profilesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "FacebookSharedPost": {
        "properties": {
          "author": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "Its author."
          },
          "id": {
            "description": "Its post ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Its URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "author"
        ],
        "type": "object"
      },
      "FacebookTranscriptResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Transcript"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "FacebookWebResultSpecific": {
        "properties": {
          "account_type": {
            "description": "What the index's text says the account is: page (Facebook describes it with counts, as it does a Page, and a person in professional mode) or person (Facebook's \"is on Facebook\" text). Null when the text doesn't say. New values may be added.",
            "enum": [
              "page",
              "person",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "like_count": {
            "description": "The Page's likes as the index's snippet states them; null when it does not, as for most Pages, which show followers instead.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "place": {
            "description": "Where the account is, as the index's snippet names it after its name (a city, usually); null when it does not.",
            "type": [
              "string",
              "null"
            ]
          },
          "talking_about_count": {
            "description": "How many people Facebook counted as talking about the account, as the index's snippet states it; null when it does not.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "were_here_count": {
            "description": "How many people have checked in at the account's place, as the index's snippet states it; null when it does not.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "account_type",
          "like_count",
          "talking_about_count",
          "were_here_count",
          "place"
        ],
        "type": "object"
      },
      "GoogleAdLocation": {
        "properties": {
          "country_code": {
            "description": "ISO 3166-1 alpha-2 code of its country; null when not resolved.",
            "type": [
              "string",
              "null"
            ]
          },
          "criterion_id": {
            "description": "Google Ads geo target criterion ID (2840 is the United States).",
            "type": "string"
          },
          "full_name": {
            "description": "The name with the regions it lies in (California, United States); null when not resolved.",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "The location's name (California); null when Google did not resolve it.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "criterion_id",
          "name",
          "full_name",
          "country_code"
        ],
        "type": "object"
      },
      "GoogleAdRegion": {
        "properties": {
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country code.",
            "type": "string"
          },
          "first_shown_at": {
            "description": "First day shown there, RFC 3339 UTC (date-only: approximate_fields); null when not shown.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "impressions": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Range"
              },
              {
                "type": "null"
              }
            ],
            "description": "Times shown there, Google's range; null when not disclosed."
          },
          "last_shown_at": {
            "description": "Last day shown there, RFC 3339 UTC (date-only: approximate_fields); null when not shown.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "services": {
            "description": "Times shown there on each Google service; [] when not disclosed.",
            "items": {
              "$ref": "#/components/schemas/GoogleAdServiceImpressions"
            },
            "type": "array"
          }
        },
        "required": [
          "country_code",
          "first_shown_at",
          "last_shown_at",
          "impressions",
          "services"
        ],
        "type": "object"
      },
      "GoogleAdResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Ad"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "GoogleAdServiceImpressions": {
        "properties": {
          "impressions": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Range"
              },
              {
                "type": "null"
              }
            ],
            "description": "Times shown on it, Google's range (a lower bound of 0 when Google shows only \"under\" an upper bound)."
          },
          "service": {
            "description": "The Google service. New values may be added; treat unknown values as other.",
            "enum": [
              "google_search",
              "google_maps",
              "google_play",
              "google_shopping",
              "youtube",
              "other"
            ],
            "type": "string"
          }
        },
        "required": [
          "service",
          "impressions"
        ],
        "type": "object"
      },
      "GoogleAdSpecific": {
        "properties": {
          "days_shown": {
            "description": "Days the ad was shown (the center's \"Ran for\"); null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_synthetic": {
            "description": "The advertiser disclosed synthetic (digitally altered or generated) content, as the ad's page labels it; false when it shows no such label.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "product_category": {
            "description": "The product category Google files a Shopping ad under (Apparel & Accessories); null otherwise.",
            "type": [
              "string",
              "null"
            ]
          },
          "regions": {
            "description": "Per country it was shown in: when, how often and on which Google services; [] when not shown (in unknown_fields).",
            "items": {
              "$ref": "#/components/schemas/GoogleAdRegion"
            },
            "type": "array"
          },
          "targeting": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/GoogleAdTargeting"
              },
              {
                "type": "null"
              }
            ],
            "description": "Whom the advertiser selected; null when not disclosed."
          },
          "topic": {
            "description": "The ad's topic as Google labels it (Sports & Fitness); null when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "days_shown",
          "topic",
          "product_category",
          "is_synthetic",
          "regions",
          "targeting"
        ],
        "type": "object"
      },
      "GoogleAdTargeting": {
        "properties": {
          "age_ranges": {
            "description": "Age ranges included (18-24, 25-34, 35-44, 45-54, 55-64, 65+, unknown); [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "criteria": {
            "description": "The kinds of criteria the advertiser included or excluded (the EU disclosure); [] when not disclosed.",
            "items": {
              "$ref": "#/components/schemas/GoogleAdTargetingCriterion"
            },
            "type": "array"
          },
          "excluded_age_ranges": {
            "description": "Age ranges excluded; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "excluded_genders": {
            "description": "Genders excluded; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "excluded_locations": {
            "description": "Locations excluded; [] when none.",
            "items": {
              "$ref": "#/components/schemas/GoogleAdLocation"
            },
            "type": "array"
          },
          "genders": {
            "description": "Genders included (male, female, unknown); [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "locations": {
            "description": "Locations included; [] when none.",
            "items": {
              "$ref": "#/components/schemas/GoogleAdLocation"
            },
            "type": "array"
          }
        },
        "required": [
          "age_ranges",
          "excluded_age_ranges",
          "genders",
          "excluded_genders",
          "locations",
          "excluded_locations",
          "criteria"
        ],
        "type": "object"
      },
      "GoogleAdTargetingCriterion": {
        "properties": {
          "category": {
            "description": "The kind of criteria. New values may be added; treat unknown values as other.",
            "enum": [
              "demographics",
              "locations",
              "contextual",
              "topics_of_interest",
              "customer_lists"
            ],
            "type": "string"
          },
          "is_excluded": {
            "description": "Criteria of this kind were excluded from the audience.",
            "type": "boolean"
          },
          "is_included": {
            "description": "Criteria of this kind were included in the audience.",
            "type": "boolean"
          }
        },
        "required": [
          "category",
          "is_included",
          "is_excluded"
        ],
        "type": "object"
      },
      "GoogleAdsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 40), last shown, most recent first with sort=newest, last shown, least recent first (topic=political) with sort=oldest, most impressions first (topic=political) with sort=popular, most spent first (topic=political) with sort=spend.",
            "items": {
              "$ref": "#/components/schemas/Ad"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "GoogleAdvertiserResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile",
            "description": "In Google's words: `metrics.post_count` is ads."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "GoogleElectionAdvertiser": {
        "properties": {
          "ad_count": {
            "description": "Election ads the center shows for the advertiser, exact.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "country_codes": {
            "description": "ISO 3166-1 alpha-2 codes of the countries and territories it is verified to run election ads in; [] when not shown.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "regulatory_ids": {
            "description": "The advertiser's registrations with election regulators (a US FEC committee ID, or an individual's own registration); [] when it disclosed none.",
            "items": {
              "$ref": "#/components/schemas/GoogleRegulatoryID"
            },
            "type": "array"
          }
        },
        "required": [
          "ad_count",
          "country_codes",
          "regulatory_ids"
        ],
        "type": "object"
      },
      "GoogleProfileSpecific": {
        "properties": {
          "ads": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Range"
              },
              {
                "type": "null"
              }
            ],
            "description": "The ads the center shows for the advertiser, as Google's range (equal bounds when exact), in the region the request names where it takes one; metrics.post_count is its lower bound. Null when not shown."
          },
          "election": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/GoogleElectionAdvertiser"
              },
              {
                "type": "null"
              }
            ],
            "description": "The advertiser's election-ads disclosure; null when it is not an election advertiser or the center does not show it."
          },
          "is_election_advertiser": {
            "description": "True when Google verified the advertiser to run election ads (it has a page in the center's political ads view).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "last_shown_at": {
            "description": "The last time one of the advertiser's ads was shown, RFC 3339 UTC (among the ads counted in ads); null when it has none or the center does not show it.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "legal_name": {
            "description": "The advertiser's legal name, as Google verified it; null when the center shows none.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "ads",
          "legal_name",
          "last_shown_at",
          "is_election_advertiser",
          "election"
        ],
        "type": "object"
      },
      "GoogleRegulatoryID": {
        "properties": {
          "id": {
            "description": "The identifier, as registered (C00003418).",
            "type": "string"
          },
          "type": {
            "description": "The kind of identifier. New values may be added; treat unknown values as other.",
            "enum": [
              "us_fec_id",
              "us_employer_identification_number",
              "us_state_id",
              "us_individual",
              "other"
            ],
            "type": "string"
          }
        },
        "required": [
          "type",
          "id"
        ],
        "type": "object"
      },
      "GoogleSearch_adsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 40), last shown, most recent first with sort=newest, last shown, least recent first (topic=political) with sort=oldest, most impressions first (topic=political) with sort=popular, most spent first (topic=political) with sort=spend.",
            "items": {
              "$ref": "#/components/schemas/Ad"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "GoogleSearch_advertisersResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 100), most ads first, by the center's ad counts (the upper bound, then the lower), Google's order among equals with sort=popular, Google's order, as the center's search box lists the matches with sort=relevance. In Google's words: `metrics.post_count` is ads.",
            "items": {
              "$ref": "#/components/schemas/Profile"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "GoogleSearch_suggestionsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 20), the center's search box order: on each page its advertisers, then its websites.",
            "items": {
              "$ref": "#/components/schemas/Suggestion"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "GoogleSuggestionSpecific": {
        "properties": {
          "ads": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Range"
              },
              {
                "type": "null"
              }
            ],
            "description": "The ads the center shows for an advertiser suggestion's advertiser, as Google's range (equal bounds when exact), in the region the request names where it takes one; null for a website suggestion, or when not shown."
          },
          "country_code": {
            "description": "The country an advertiser suggestion's advertiser is based in, an ISO 3166-1 alpha-2 code; null for a website suggestion, or when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "country_code",
          "ads"
        ],
        "type": "object"
      },
      "GoogleTrendMetrics": {
        "properties": {
          "search_count": {
            "description": "Searches for the term in the board's window, as the lower bound of Google's volume bucket (500 for \"500+\"), always approximate.",
            "format": "int64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "search_count"
        ],
        "type": "object"
      },
      "GoogleTrendSpecific": {
        "properties": {
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country whose searches the trend counts; null for a worldwide board.",
            "type": [
              "string",
              "null"
            ]
          },
          "ended_at": {
            "description": "When it stopped trending, RFC 3339 UTC; null while it is active (is_active) or when unknown.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "growth": {
            "description": "How much the term's searches rose since it started trending, a fraction (1 = +100 %), in Google's steps; Google caps it at 10 (+1,000 %), a lower bound then (listed in approximate_fields).",
            "format": "double",
            "minimum": 0,
            "type": [
              "number",
              "null"
            ]
          },
          "history": {
            "description": "How much the term was searched over time, oldest first, each interval relative to the series' peak (1); [] on a board, which does not read the series (listed in unknown_fields): a trend's own endpoint fills it.",
            "items": {
              "$ref": "#/components/schemas/TrendPoint"
            },
            "type": "array"
          },
          "is_active": {
            "description": "Still trending: Google shows it as active (ended_at is null).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/GoogleTrendMetrics",
            "description": "Google's counts for the trend; null = not shown."
          },
          "related_searches": {
            "description": "Other searches Google groups under the trend, in its order (the term itself left out); each a term of its own. [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "started_at": {
            "description": "When the term started trending, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "country_code",
          "growth",
          "started_at",
          "ended_at",
          "is_active",
          "related_searches",
          "metrics",
          "history"
        ],
        "type": "object"
      },
      "Hashtag": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform or parsed from display text (\"36M videos\": metrics.post_count). [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "description": {
            "description": "The hashtag's description as its page shows it; null when it has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native hashtag ID (TikTok's challenge ID, Threads' tag ID); on platforms whose public pages key a hashtag by its name (Instagram, YouTube, Facebook, X), the name lowercased.",
            "type": "string"
          },
          "metrics": {
            "$ref": "#/components/schemas/HashtagMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "name": {
            "description": "The tag without #, as the platform shows it (case kept). Threads tags may contain spaces (\"book club\").",
            "type": "string"
          },
          "platform": {
            "description": "Platform ID (tiktok, instagram, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/HashtagPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "thumbnail_url": {
            "description": "The hashtag's own picture (not one of its posts' images); null when it has none. Platform CDN URLs can expire.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Canonical hashtag page URL (for a multi-word Threads tag, its tag search page).",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "name",
          "url",
          "description",
          "thumbnail_url",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "HashtagMetrics": {
        "properties": {
          "post_count": {
            "description": "Posts carrying the tag, as the platform counts them; rounded on YouTube and Threads (see approximate_fields).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "post_count"
        ],
        "type": "object"
      },
      "HashtagPlatformSpecific": {
        "properties": {
          "instagram": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InstagramHashtagSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Instagram hashtag's own fields."
          },
          "threads": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ThreadsHashtagSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Threads tag's own fields."
          },
          "tiktok": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokHashtagSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A TikTok hashtag's own fields."
          },
          "youtube": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/YouTubeHashtagSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A YouTube hashtag's own fields."
          }
        },
        "type": "object"
      },
      "HashtagRef": {
        "properties": {
          "id": {
            "description": "The hashtag's ID as the platform's hashtag endpoints key it: its native ID, or the name lowercased where the platform's pages key a hashtag by name (Instagram).",
            "type": "string"
          },
          "metrics": {
            "$ref": "#/components/schemas/HashtagMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "name": {
            "description": "The tag without #, as the platform shows it (case kept).",
            "type": "string"
          },
          "url": {
            "description": "Canonical hashtag page URL.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "url",
          "metrics"
        ],
        "type": "object"
      },
      "HashtagSummary": {
        "properties": {
          "description": {
            "description": "The hashtag's description as the index's snippet quotes it; null when it quotes none (a platform's generic page text is not one).",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "The hashtag's ID as the platform's hashtag endpoints key it; null until the result is filled.",
            "type": [
              "string",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/HashtagMetrics",
            "description": "Counts as the index's text states them (\"36.2M posts\"; rounded, as old as the index's copy: see approximate_fields), or the platform's current ones once filled; null = not stated."
          },
          "name": {
            "description": "The tag without #, as the matched link or the index's title spells it (case kept where the title shows it).",
            "type": "string"
          },
          "thumbnail_url": {
            "description": "The hashtag's own picture; null until the result is filled.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Canonical hashtag page URL (equals the result's url).",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "url",
          "description",
          "thumbnail_url",
          "metrics"
        ],
        "type": "object"
      },
      "InputRef": {
        "properties": {
          "id": {
            "description": "Platform-native ID of the item; null when it is only known after the fetch and the request failed.",
            "type": [
              "string",
              "null"
            ]
          },
          "kind": {
            "description": "What the input points to (profile, video, post, …). New values may be added; treat unknown values as other.",
            "type": "string"
          },
          "url": {
            "description": "Canonical URL of the item; null when unknown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "kind",
          "id",
          "url"
        ],
        "type": "object"
      },
      "InstagramCommentResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Comment"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "InstagramCommentSpecific": {
        "properties": {
          "gif_url": {
            "description": "The GIF the comment is (Instagram's GIPHY picker; text is then usually empty), on Meta's CDN; the URL is signed and expires within days. null when the comment has no GIF or the source does not show it (the post page's first comments).",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "gif_url"
        ],
        "type": "object"
      },
      "InstagramCommentsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 24), newest first.",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramEmbedResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Embed"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "InstagramEngagementResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Engagement"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "InstagramHashtagResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Hashtag"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "InstagramHashtagSpecific": {
        "properties": {
          "is_restricted": {
            "description": "Instagram restricts the tag: its posts are hidden (a tag it reports as sensitive), though it exists.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_trending": {
            "description": "Instagram marks the tag trending; null where it does not say (search results).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "tag_id": {
            "description": "Instagram's own numeric ID of the hashtag; null where the source does not show it (a tag Instagram withholds).",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "is_restricted",
          "is_trending",
          "tag_id"
        ],
        "type": "object"
      },
      "InstagramHashtag_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 24), Instagram's ranking of the hashtag's reels (its public results page's order).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramHighlightsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 10), the order of the account's highlights tray on its profile.",
            "items": {
              "$ref": "#/components/schemas/Playlist"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramLink": {
        "properties": {
          "url": {
            "description": "The linked page, as the author shared it (Instagram's l.instagram.com redirect removed).",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "url"
        ],
        "type": "object"
      },
      "InstagramPlaceResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Place"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "InstagramPlaceSpecific": {
        "properties": {
          "facebook_place_id": {
            "description": "ID of the Facebook place (Page) behind the location: the id of the same place on facebook. Null when none is linked or the source does not show it.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "facebook_place_id"
        ],
        "type": "object"
      },
      "InstagramPlace_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 18), newest first with sort=newest, Instagram's Top posts for the location (its ranking) with sort=popular.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramPlaylist_storiesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), oldest first.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramPostLocation": {
        "properties": {
          "id": {
            "description": "Instagram location ID (equals the place's id: the number in instagram.com/explore/locations/<id>/).",
            "type": "string"
          },
          "latitude": {
            "description": "WGS 84 latitude in degrees (set together with longitude).",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "longitude": {
            "description": "WGS 84 longitude in degrees (set together with latitude).",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "name": {
            "description": "Place name as Instagram shows it.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The place's page on Instagram.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "url",
          "latitude",
          "longitude"
        ],
        "type": "object"
      },
      "InstagramPostResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "InstagramPostSpecific": {
        "properties": {
          "is_ai_generated": {
            "description": "Instagram shows its AI label (made or edited with AI); false when it shows none.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "link": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InstagramLink"
              },
              {
                "type": "null"
              }
            ],
            "description": "The link a story's link sticker (or swipe-up link) opens; null when none, and on every post that is not a story."
          },
          "location": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InstagramPostLocation"
              },
              {
                "type": "null"
              }
            ],
            "description": "The tagged place; null when none or not shown by the endpoint's source."
          }
        },
        "required": [
          "is_ai_generated",
          "location",
          "link"
        ],
        "type": "object"
      },
      "InstagramPostsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 12), newest first.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "InstagramProfileSpecific": {
        "properties": {
          "account_type": {
            "description": "The kind of account Instagram says it is: personal, or one of its professional kinds, business or creator (an account picks one; it says nothing of whether a person or an organization runs it). Null when the source does not show it. New values may be added; treat unknown values as unknown.",
            "enum": [
              "personal",
              "business",
              "creator",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "fbid": {
            "description": "The account's Meta-wide ID (17841…), the one Meta's Instagram Graph API uses; id is Instagram's own user ID. Null when the source does not show it.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_highlights_shown": {
            "description": "True when the profile shows story highlights, false when it shows none; null when unknown (private accounts, or a source that does not show them).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_memorialized": {
            "description": "True when Instagram has memorialized the account (its owner has died), false otherwise; null when unknown.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_story_live": {
            "description": "True when the account has a story up now (stories last 24 hours), false when it has none; null when unknown (Instagram does not say for private accounts).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "pronouns": {
            "description": "The pronouns the owner chose to show on the profile, as shown; [] when none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "fbid",
          "is_memorialized",
          "is_story_live",
          "is_highlights_shown",
          "account_type",
          "pronouns"
        ],
        "type": "object"
      },
      "InstagramReelsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 12), newest first.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramSearch_hashtagsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 55), Instagram's search ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/Hashtag"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramSearch_placesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramSearch_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 24), Instagram's ranking for the keyword (its popular page's order).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramSearch_profilesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramSearch_soundsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramSearch_suggestionsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 56), the exact account first, then Instagram's tag search ranking.",
            "items": {
              "$ref": "#/components/schemas/Suggestion"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramSimilar_profilesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), Instagram's suggestion order.",
            "items": {
              "$ref": "#/components/schemas/Profile"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramSoundResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Sound"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "InstagramSoundSourcePost": {
        "properties": {
          "id": {
            "description": "The reel's shortcode: its post ID (equals post.id of instagram.post).",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The reel's link (instagram.com/reel/<id>/).",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "url"
        ],
        "type": "object"
      },
      "InstagramSoundSpecific": {
        "properties": {
          "asset_id": {
            "description": "ID of a licensed track's audio asset (not the sound's page ID); null for original audio.",
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "description": "When the creator's original audio was created (RFC 3339 UTC): when the reel it comes from was published; null for a licensed track.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "is_explicit": {
            "description": "Instagram marks the track explicit.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_lyrics_shown": {
            "description": "Instagram has the licensed track's lyrics and shows them with it; null for original audio.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_trending": {
            "description": "Instagram labels the audio trending in reels.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "source_post": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InstagramSoundSourcePost"
              },
              {
                "type": "null"
              }
            ],
            "description": "The reel an original audio comes from (the first published with it); null for a licensed track."
          }
        },
        "required": [
          "asset_id",
          "is_explicit",
          "is_trending",
          "is_lyrics_shown",
          "created_at",
          "source_post"
        ],
        "type": "object"
      },
      "InstagramSound_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 12), Instagram's ranking of the audio's reels (the order its audio page shows).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramStoryResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "InstagramSuggestionSpecific": {
        "properties": {
          "tag_id": {
            "description": "Instagram's own numeric ID of a hashtag suggestion's tag; null for every other type.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "tag_id"
        ],
        "type": "object"
      },
      "InstagramTopicResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Topic"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "InstagramTopicSpecific": {
        "properties": {
          "is_category": {
            "description": "Instagram shows the topic as a category (a broad topic made of narrower ones, without a post count of its own); null when the source cannot tell.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "post_count": {
            "description": "Reels Instagram counts under the topic, cut to the digits it shows (46M for 46,656,326; in approximate_fields); null when the page shows none.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "source_urls": {
            "description": "Web pages the description draws on, in the order its superscript markers number them (¹ is the first); [] when it cites none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "is_category",
          "source_urls",
          "post_count"
        ],
        "type": "object"
      },
      "InstagramTranscriptResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Transcript"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "InstagramTrending_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 40), Instagram's reels feed order (a fresh selection on each first page).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "InstagramUsernameResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Username"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "KickCategory": {
        "properties": {
          "banner_url": {
            "description": "The category's banner image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Kick's category ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "Its name (Just Chatting).",
            "type": [
              "string",
              "null"
            ]
          },
          "parent_slug": {
            "description": "The parent category it is filed under (irl, games).",
            "type": [
              "string",
              "null"
            ]
          },
          "slug": {
            "description": "Its name in links (kick.com/category/just-chatting).",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "parent_slug",
          "banner_url"
        ],
        "type": "object"
      },
      "KickPostResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "KickPostSpecific": {
        "properties": {
          "category": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KickCategory"
              },
              {
                "type": "null"
              }
            ],
            "description": "What the channel was streaming when the clip was made."
          },
          "clipped_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The account that made the clip, which may be a bot taking chat commands; author is the channel it was clipped from. Its id is null: see clipped_by_user_id."
          },
          "clipped_by_user_id": {
            "description": "Kick's user number of clipped_by, which is not its channel's ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "livestream_id": {
            "description": "Kick's ID of the broadcast the clip was cut from.",
            "type": [
              "string",
              "null"
            ]
          },
          "started_at": {
            "description": "The moment of the broadcast the clip starts at, RFC 3339 UTC; published_at is when it was made.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "vod": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KickVOD"
              },
              {
                "type": "null"
              }
            ],
            "description": "The saved broadcast the clip comes from; null when Kick keeps none (the broadcast's video was deleted or never saved) or the answer came from a source that can't link to it."
          }
        },
        "required": [
          "started_at",
          "livestream_id",
          "category",
          "vod",
          "clipped_by",
          "clipped_by_user_id"
        ],
        "type": "object"
      },
      "KickTranscriptResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Transcript"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "KickVOD": {
        "properties": {
          "id": {
            "description": "The video's ID, as in its link.",
            "type": [
              "string",
              "null"
            ]
          },
          "offset_ms": {
            "description": "Where in the video the clip starts, in milliseconds.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "title": {
            "description": "The video's title.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The video's page.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "offset_ms"
        ],
        "type": "object"
      },
      "KomiItemLink": {
        "properties": {
          "type": {
            "description": "Komi's name for the service, lowercase: spotify, apple_music, youtube_music, deezer, apple_podcast, … New values may be added.",
            "type": "string"
          },
          "url": {
            "description": "The release or the episode on that service.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "type",
          "url"
        ],
        "type": "object"
      },
      "KomiPageItem": {
        "properties": {
          "coupon_code": {
            "description": "The discount code a link's own page on Komi shows anyone who follows it; null when it has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "currency": {
            "description": "ISO 4217 currency of price; null when the item has no price or Komi does not say.",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "description": "The text of a text module, a gallery image's caption, or a product's description.",
            "type": [
              "string",
              "null"
            ]
          },
          "group": {
            "description": "The name of the group the item sits in on the page; null when it is in none.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Komi's ID of the item; null for items Komi reads from another service (a shop's or Bandsintown's).",
            "type": [
              "string",
              "null"
            ]
          },
          "is_sold_out": {
            "description": "Whether an event is sold out; null for anything but an event.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "links": {
            "description": "For music and podcasts, the same release on each service, in the page's order; [] for everything else.",
            "items": {
              "$ref": "#/components/schemas/KomiItemLink"
            },
            "type": "array"
          },
          "location": {
            "description": "An event's place as the page shows it; null otherwise.",
            "type": [
              "string",
              "null"
            ]
          },
          "price": {
            "description": "A product's price as the page shows it, in major units of currency; 0 is a free digital download; null when the item has no price or the page shows none.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "section": {
            "description": "The title the page shows above the item's module; null when it shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "starts_at": {
            "description": "When an event starts, RFC 3339 UTC; null otherwise. A Bandsintown or Seated time has no zone and is read as UTC (listed in approximate_fields).",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "The item's image; null when it has none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The item's label: a link's text, a product's name, a video's or a release's title.",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "Komi's name for the kind of module, lowercase: link, product, digital_product, youtube_video, youtube_short, tiktok_video, instagram_reel, music, podcast, events, bandsintown, seated, text, media_gallery, shop_my_shelf, mail_link, data_capture_signup, form_data, … New values may be added: treat an unknown one as a generic item.",
            "type": "string"
          },
          "url": {
            "description": "Where the item leads: the link's target (a mailto: link for a mail_link), the product's page, the video, the release's or the digital product's page on Komi, an event's tickets. Null for a form or a text.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "venue": {
            "description": "An event's venue; null otherwise.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "group",
          "section",
          "title",
          "url",
          "thumbnail_url",
          "description",
          "price",
          "currency",
          "coupon_code",
          "links",
          "starts_at",
          "venue",
          "location",
          "is_sold_out"
        ],
        "type": "object"
      },
      "KomiPageResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "KomiProfileSpecific": {
        "properties": {
          "display_name_image_url": {
            "description": "The artwork the page shows as its name, when it has one; null otherwise.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "first_name": {
            "description": "The owner's first name as entered on Komi; null when empty.",
            "type": [
              "string",
              "null"
            ]
          },
          "items": {
            "description": "What the page shows, flattened in the page's order: links, products, videos, music, podcasts, events, text and galleries. Modules the owner has hidden are not returned; [] when the page shows nothing (listed in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/KomiPageItem"
            },
            "type": "array"
          },
          "last_name": {
            "description": "The owner's last name as entered on Komi; null when empty.",
            "type": [
              "string",
              "null"
            ]
          },
          "social_links": {
            "description": "The page's row of social and music profiles and contact links, in the page's order; [] when it has none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/KomiSocialLink"
            },
            "type": "array"
          }
        },
        "required": [
          "first_name",
          "last_name",
          "display_name_image_url",
          "social_links",
          "items"
        ],
        "type": "object"
      },
      "KomiSocialLink": {
        "properties": {
          "type": {
            "description": "Komi's name for the service, lowercase: instagram, tiktok, youtube, twitter, facebook, snapchat, spotify, apple_music, website, email, whatsapp, … New values may be added.",
            "type": "string"
          },
          "url": {
            "description": "The link, as the owner entered it (https:// added when it had no scheme); an email address as a mailto: link.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "type",
          "url"
        ],
        "type": "object"
      },
      "KwaiDuetSource": {
        "properties": {
          "display_name": {
            "description": "The source author's display name, as the duet shows it.",
            "type": [
              "string",
              "null"
            ]
          },
          "post_id": {
            "description": "The source post's ID; null when the source does not state it exactly.",
            "type": [
              "string",
              "null"
            ]
          },
          "user_id": {
            "description": "The source author's numeric user ID, accepted as a handle.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "post_id",
          "user_id",
          "display_name"
        ],
        "type": "object"
      },
      "KwaiMusic": {
        "properties": {
          "author_name": {
            "description": "Who Kwai credits for the sound.",
            "type": [
              "string",
              "null"
            ]
          },
          "cover_url": {
            "description": "Sound cover image URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "duration_ms": {
            "description": "Sound length in milliseconds.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "id": {
            "description": "Sound ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_original": {
            "description": "An original sound a creator uploaded (false: a catalogue track).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "play_url": {
            "description": "Audio file URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "Sound title; null on most original sounds, which Kwai leaves untitled.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "author_name",
          "is_original",
          "duration_ms",
          "cover_url",
          "play_url"
        ],
        "type": "object"
      },
      "KwaiPlace": {
        "properties": {
          "address": {
            "description": "Address line.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Place ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "latitude": {
            "description": "Latitude in degrees.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "longitude": {
            "description": "Longitude in degrees.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "name": {
            "description": "Place name.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "address",
          "latitude",
          "longitude"
        ],
        "type": "object"
      },
      "KwaiPostResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "KwaiPostSpecific": {
        "properties": {
          "author_user_id": {
            "description": "The author's numeric user ID, also accepted as a handle; null when the source does not state it (author.id, the account's encrypted ID, is always the same account).",
            "type": [
              "string",
              "null"
            ]
          },
          "author_verified_description": {
            "description": "What the author's verification badge says (Conta Oficial); null when the account has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "category": {
            "description": "The topic Kwai files the post under (Dance, Comedy&Funny), in English; null when it files it under none.",
            "type": [
              "string",
              "null"
            ]
          },
          "duet_source": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KwaiDuetSource"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post this one duets; null when it is no duet."
          },
          "is_ai_generated": {
            "description": "Kwai labels the post as AI-generated; null when the source does not state it.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "music": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KwaiMusic"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post's sound; null when Kwai names none."
          },
          "place": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KwaiPlace"
              },
              {
                "type": "null"
              }
            ],
            "description": "The place tagged on the post; null when none."
          },
          "subcategory": {
            "description": "The narrower topic within category (Fashion dance); null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "tagged_accounts": {
            "description": "The accounts the caption tags, in order; [] when none. mentions holds the names written in the caption by hand.",
            "items": {
              "$ref": "#/components/schemas/KwaiTaggedAccount"
            },
            "type": "array"
          }
        },
        "required": [
          "music",
          "author_user_id",
          "author_verified_description",
          "category",
          "subcategory",
          "is_ai_generated",
          "tagged_accounts",
          "place",
          "duet_source"
        ],
        "type": "object"
      },
      "KwaiPostsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), newest first.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "KwaiProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "KwaiProfileSpecific": {
        "properties": {
          "gender": {
            "description": "The gender the account states: M or F. Null when it states none.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_banned": {
            "description": "True when Kwai writes the account as banned, and it gives no reason. Kwai then blanks the account's name, picture, bio and badge, so is_verified is null, and lists no posts whatever metrics.post_count says.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "likes_given_count": {
            "description": "Likes the account has given. Null when it hides them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "playlist_count": {
            "description": "Playlists the account has. Null when Kwai states none, which is also how it writes an account without any, and on an answer from Kwai's API.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "private_post_count": {
            "description": "Posts the account keeps to itself, as Kwai counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "user_id": {
            "description": "The account's numeric ID, as a string. Accepted as input like id.",
            "type": [
              "string",
              "null"
            ]
          },
          "verified_description": {
            "description": "The label Kwai gives the account's badge, in the account's language (Criador(a) de Comédia, Conta Oficial). Null without a badge.",
            "type": [
              "string",
              "null"
            ]
          },
          "verified_type": {
            "description": "Kwai's number for the kind of badge: 2 on creators and 3 on the official account in the accounts checked. Null without a badge.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "user_id",
          "gender",
          "verified_description",
          "verified_type",
          "private_post_count",
          "likes_given_count",
          "playlist_count",
          "is_banned"
        ],
        "type": "object"
      },
      "KwaiTaggedAccount": {
        "properties": {
          "label": {
            "description": "The name the caption shows for it: its display name or username.",
            "type": [
              "string",
              "null"
            ]
          },
          "user_id": {
            "description": "The account's numeric user ID, accepted as a handle.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "user_id",
          "label"
        ],
        "type": "object"
      },
      "Link": {
        "properties": {
          "title": {
            "description": "Link label shown by the platform.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Link target, absolute (https:// is added where the platform stores the link without a scheme).",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "url",
          "title"
        ],
        "type": "object"
      },
      "LinkbioProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "LinkbioProfileSpecific": {
        "properties": {
          "custom_domain_url": {
            "description": "The account's own domain for this page, when it has one (https://7ad.sa for lnk.bio/7adsa). Null when it has none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "emails": {
            "description": "Email addresses the page lists as contact icons, links, contact cards or in its bio; [] if none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "link_count": {
            "description": "How many links the page's link list holds, icons not included: what was read when that is all of it, else Lnk.Bio's own count, which can include embedded players. Null when neither is known.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "linked_username": {
            "description": "The @name the page shows under its picture, without the @: usually the account's Instagram username, which can differ from the page's own name (username). Null when the page shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "phones": {
            "description": "Phone numbers the page lists as contact icons, links or contact cards, as written; [] if none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "social_links": {
            "description": "The page's row of social and contact icons, in order; [] if none.",
            "items": {
              "$ref": "#/components/schemas/LinkbioSocialLink"
            },
            "type": "array"
          }
        },
        "required": [
          "linked_username",
          "emails",
          "phones",
          "social_links",
          "link_count",
          "custom_domain_url"
        ],
        "type": "object"
      },
      "LinkbioSocialLink": {
        "properties": {
          "platform": {
            "description": "The icon's name as Lnk.Bio labels it (Instagram, TikTok, Website, WhatsApp, Spotify, …).",
            "type": "string"
          },
          "url": {
            "description": "Where the icon links to.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "url"
        ],
        "type": "object"
      },
      "LinkedInAdCompany": {
        "properties": {
          "location": {
            "description": "Where the company is, as the card writes it; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "size": {
            "description": "The company's size as the card writes it (10,001+ employees); null when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "size",
          "location"
        ],
        "type": "object"
      },
      "LinkedInAdCountry": {
        "properties": {
          "country": {
            "description": "The country's name, as the library writes it.",
            "type": [
              "string",
              "null"
            ]
          },
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country code; null when the name is none the library's country list has.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_under_one_percent": {
            "description": "The library writes the share as less than one percent.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "share_percent": {
            "description": "Share of the ad's impressions, a whole percent as the library rounds it; null when under one percent.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "country",
          "country_code",
          "share_percent",
          "is_under_one_percent"
        ],
        "type": "object"
      },
      "LinkedInAdCriterion": {
        "properties": {
          "is_excluded": {
            "description": "The advertiser excluded by this criterion.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_targeted": {
            "description": "The advertiser targeted by this criterion.",
            "type": [
              "boolean",
              "null"
            ]
          }
        },
        "required": [
          "is_targeted",
          "is_excluded"
        ],
        "type": "object"
      },
      "LinkedInAdDocument": {
        "properties": {
          "page_count": {
            "description": "How many pages it has; null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "title": {
            "description": "The document's title; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "title",
          "page_count"
        ],
        "type": "object"
      },
      "LinkedInAdEvent": {
        "properties": {
          "ends_at": {
            "description": "When it ends, RFC 3339 UTC; null when not shown.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "description": "Where it happens, as written (Online); null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "organizer": {
            "description": "Who hosts the event; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "starts_at": {
            "description": "When it starts, RFC 3339 UTC; null when not shown.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "organizer",
          "location",
          "starts_at",
          "ends_at"
        ],
        "type": "object"
      },
      "LinkedInAdJob": {
        "properties": {
          "company": {
            "description": "The company the job is at; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "description": "The job's location, as written; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "company",
          "location"
        ],
        "type": "object"
      },
      "LinkedInAdMessage": {
        "properties": {
          "buttons": {
            "description": "The message's buttons, in order; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "sender_avatar_url": {
            "description": "The sender's picture; null when not shown.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "sender_name": {
            "description": "The person the message is sent as; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "sender_name",
          "sender_avatar_url",
          "buttons"
        ],
        "type": "object"
      },
      "LinkedInAdSegments": {
        "properties": {
          "excluded": {
            "description": "Excluded; [] when none are listed.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "included": {
            "description": "Targeted; [] when none are listed.",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "included",
          "excluded"
        ],
        "type": "object"
      },
      "LinkedInAdSpecific": {
        "properties": {
          "company": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdCompany"
              },
              {
                "type": "null"
              }
            ],
            "description": "The company a company discovery ad presents; null on every other format."
          },
          "creative_type": {
            "description": "LinkedIn's code for the ad's format (SPONSORED_STATUS_UPDATE, SPONSORED_VIDEO, SPONSORED_INMAILS, JOBS_V2, …), finer than type; null when the library shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "document": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdDocument"
              },
              {
                "type": "null"
              }
            ],
            "description": "The document a document ad shows; null on every other format."
          },
          "event": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdEvent"
              },
              {
                "type": "null"
              }
            ],
            "description": "The event an event ad promotes; null on every other format."
          },
          "format": {
            "description": "The ad's format as the library labels it (Single Image Ad, Message Ad, Company Discovery Ad, …); null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "impressions_by_country": {
            "description": "Each country's share of the ad's impressions, as the library lists them; [] when not shown (in unknown_fields).",
            "items": {
              "$ref": "#/components/schemas/LinkedInAdCountry"
            },
            "type": "array"
          },
          "is_deleted": {
            "description": "The library says the ad was deleted; false when it shows no such notice.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "job": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdJob"
              },
              {
                "type": "null"
              }
            ],
            "description": "The job a job ad promotes; null on every other format."
          },
          "message": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdMessage"
              },
              {
                "type": "null"
              }
            ],
            "description": "A message ad's sender and buttons; null on every other format."
          },
          "newsletter": {
            "description": "The newsletter an article ad's article belongs to; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "poster": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The account the ad appears from: the advertiser, or a member whose post it promotes; null when the preview names none."
          },
          "poster_title": {
            "description": "The line under the poster's name (a member's headline); null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "targeting": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdTargeting"
              },
              {
                "type": "null"
              }
            ],
            "description": "Whom the advertiser selected; null when not disclosed."
          }
        },
        "required": [
          "creative_type",
          "format",
          "is_deleted",
          "poster",
          "poster_title",
          "impressions_by_country",
          "targeting",
          "message",
          "job",
          "event",
          "document",
          "newsletter",
          "company"
        ],
        "type": "object"
      },
      "LinkedInAdTargeting": {
        "properties": {
          "audience": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdCriterion"
              },
              {
                "type": "null"
              }
            ],
            "description": "Audience criteria; null when not shown."
          },
          "company": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdCriterion"
              },
              {
                "type": "null"
              }
            ],
            "description": "Company criteria; null when not shown."
          },
          "demographic": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdCriterion"
              },
              {
                "type": "null"
              }
            ],
            "description": "Demographic criteria; null when not shown."
          },
          "education": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdCriterion"
              },
              {
                "type": "null"
              }
            ],
            "description": "Education criteria; null when not shown."
          },
          "job": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdCriterion"
              },
              {
                "type": "null"
              }
            ],
            "description": "Job criteria; null when not shown."
          },
          "languages": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdSegments"
              },
              {
                "type": "null"
              }
            ],
            "description": "The profile languages targeted or excluded; null when not shown."
          },
          "locations": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdSegments"
              },
              {
                "type": "null"
              }
            ],
            "description": "The locations targeted or excluded, in the language of the advertiser's account; null when not shown."
          },
          "member_interests": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAdCriterion"
              },
              {
                "type": "null"
              }
            ],
            "description": "Member interests and traits criteria; null when not shown."
          }
        },
        "required": [
          "languages",
          "locations",
          "audience",
          "demographic",
          "company",
          "education",
          "job",
          "member_interests"
        ],
        "type": "object"
      },
      "LinkedInAddress": {
        "properties": {
          "city": {
            "description": "City; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country code; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "postal_code": {
            "description": "Postal code; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "region": {
            "description": "State, province or region, as written; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "street": {
            "description": "Street address; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "street",
          "city",
          "region",
          "postal_code",
          "country_code"
        ],
        "type": "object"
      },
      "LinkedInArticleCard": {
        "properties": {
          "comment_count": {
            "description": "Its comments.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "description": {
            "description": "Its first lines.",
            "type": [
              "string",
              "null"
            ]
          },
          "like_count": {
            "description": "Its reactions.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "published_on": {
            "description": "The day it was published, as a date (YYYY-MM-DD).",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The article's title.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Its link.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "title",
          "url",
          "description",
          "published_on",
          "like_count",
          "comment_count"
        ],
        "type": "object"
      },
      "LinkedInCertification": {
        "properties": {
          "credential_id": {
            "description": "The credential's ID, as the member wrote it; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "expires_on": {
            "description": "When it expires, a year or a month; null when it does not or when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "issued_on": {
            "description": "When it was issued, a year or a month; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "issuer": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The issuing organization, with its Page's link when it has one; null when not shown."
          },
          "name": {
            "description": "The license or certification.",
            "type": "string"
          },
          "url": {
            "description": "Its credential link; null when it has none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "url",
          "issuer",
          "issued_on",
          "expires_on",
          "credential_id"
        ],
        "type": "object"
      },
      "LinkedInCourse": {
        "properties": {
          "name": {
            "description": "The course.",
            "type": "string"
          },
          "number": {
            "description": "Its course number, as written (BUS M 520); null when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "number"
        ],
        "type": "object"
      },
      "LinkedInDocument": {
        "properties": {
          "manifest_url": {
            "description": "The manifest LinkedIn's document viewer reads the pages from; the document's own download needs a login.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "page_count": {
            "description": "How many pages the document has (media has the first ones).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "title": {
            "description": "The document's title.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "title",
          "page_count",
          "manifest_url"
        ],
        "type": "object"
      },
      "LinkedInEducation": {
        "properties": {
          "degree": {
            "description": "The degree and field of study, as written; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "ended_on": {
            "description": "When it ended, a year or a month; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "school": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The school, with its Page's link when it has one; null when not shown."
          },
          "started_on": {
            "description": "When it started, a year or a month; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "school",
          "degree",
          "started_on",
          "ended_on"
        ],
        "type": "object"
      },
      "LinkedInHonor": {
        "properties": {
          "description": {
            "description": "The member's description of it; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "issued_on": {
            "description": "When it was issued, a year or a month; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "issuer": {
            "description": "Who issued it, as written; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The honor or award.",
            "type": "string"
          }
        },
        "required": [
          "title",
          "issuer",
          "issued_on",
          "description"
        ],
        "type": "object"
      },
      "LinkedInLanguage": {
        "properties": {
          "name": {
            "description": "The language, as written.",
            "type": "string"
          },
          "proficiency": {
            "description": "The proficiency the member states (Native or bilingual proficiency, Elementary proficiency); null when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "proficiency"
        ],
        "type": "object"
      },
      "LinkedInLink": {
        "properties": {
          "image_url": {
            "description": "The card's image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "source": {
            "description": "The card's second line: the publisher or its domain.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The card's title.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The linked page (LinkedIn's redirect and tracking removed).",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "url",
          "title",
          "source",
          "image_url"
        ],
        "type": "object"
      },
      "LinkedInLocation": {
        "properties": {
          "address": {
            "description": "The address as the Page shows it, its lines joined with commas.",
            "type": "string"
          },
          "is_primary": {
            "description": "True for the location the Page marks Primary.",
            "type": "boolean"
          }
        },
        "required": [
          "address",
          "is_primary"
        ],
        "type": "object"
      },
      "LinkedInMemberRef": {
        "properties": {
          "avatar_url": {
            "description": "Profile picture URL. Platform CDN URLs can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "display_name": {
            "description": "Display name shown on the profile.",
            "type": [
              "string",
              "null"
            ]
          },
          "headline": {
            "description": "The member's headline or current organization, as the card shows it; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native account ID; null when only the handle is known.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_verified": {
            "description": "Platform verification badge; null where the platform has no badge.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "location": {
            "description": "The member's location, as the card shows it; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Canonical profile URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "username": {
            "description": "Handle without the @; null when the account has none.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "headline",
          "location",
          "id",
          "username",
          "display_name",
          "url",
          "avatar_url",
          "is_verified"
        ],
        "type": "object"
      },
      "LinkedInOrganization": {
        "properties": {
          "description": {
            "description": "The member's description of it; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "ended_on": {
            "description": "When it ended, a year or a month; null while current (is_current) or when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_current": {
            "description": "True for a membership LinkedIn shows as ongoing (to Present); false otherwise, including when no dates are shown.",
            "type": "boolean"
          },
          "name": {
            "description": "The organization.",
            "type": "string"
          },
          "position": {
            "description": "The member's position in it, as written; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "started_on": {
            "description": "When it started, a year or a month; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "position",
          "started_on",
          "ended_on",
          "is_current",
          "description"
        ],
        "type": "object"
      },
      "LinkedInPageRef": {
        "properties": {
          "avatar_url": {
            "description": "Profile picture URL. Platform CDN URLs can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "category": {
            "description": "The Page's industry, as the card shows it; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "display_name": {
            "description": "Display name shown on the profile.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native account ID; null when only the handle is known.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_verified": {
            "description": "Platform verification badge; null where the platform has no badge.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "location": {
            "description": "The Page's headquarters city and region, as the card shows it; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Canonical profile URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "username": {
            "description": "Handle without the @; null when the account has none.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "category",
          "location",
          "id",
          "username",
          "display_name",
          "url",
          "avatar_url",
          "is_verified"
        ],
        "type": "object"
      },
      "LinkedInPatent": {
        "properties": {
          "description": {
            "description": "Its description; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "inventors": {
            "description": "The other members LinkedIn lists as its inventors; [] when it lists none.",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "issued_on": {
            "description": "When it was issued: a day (2015-01-20), a month or a year; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "number": {
            "description": "Its number, as written (US 8,938,217); null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The patent's title.",
            "type": "string"
          }
        },
        "required": [
          "title",
          "number",
          "issued_on",
          "description",
          "inventors"
        ],
        "type": "object"
      },
      "LinkedInPosition": {
        "properties": {
          "company": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The organization, with its Page's link when it has one; null when not shown."
          },
          "description": {
            "description": "The member's description of it; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "ended_on": {
            "description": "When it ended, a year or a month; null while current (is_current) or when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_current": {
            "description": "True for a position LinkedIn shows as ongoing (to Present); false otherwise, including when no dates are shown.",
            "type": "boolean"
          },
          "location": {
            "description": "Where it is, as written; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "started_on": {
            "description": "When the position started, as LinkedIn shows it: a year (2015) or a month (2015-03); null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The position's title; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "title",
          "company",
          "started_on",
          "ended_on",
          "is_current",
          "location",
          "description"
        ],
        "type": "object"
      },
      "LinkedInPostComment": {
        "properties": {
          "author": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "The commenter."
          },
          "id": {
            "description": "The comment's ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "like_count": {
            "description": "Its reactions.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "published_at": {
            "description": "When it was written, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "text": {
            "description": "The comment's text.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "author",
          "text",
          "published_at",
          "like_count"
        ],
        "type": "object"
      },
      "LinkedInPostSpecific": {
        "properties": {
          "author_follower_count": {
            "description": "The author's exact follower count.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "author_headline": {
            "description": "The headline LinkedIn shows under the author's name on the post; null for a Page, whose line is its follower count.",
            "type": [
              "string",
              "null"
            ]
          },
          "content_urn": {
            "description": "The URN of the post's content (urn:li:share:<id> or urn:li:ugcPost:<id>): another number for the same post, which links and LinkedIn's own APIs can name it by. On an article, the article's feed post.",
            "type": [
              "string",
              "null"
            ]
          },
          "document": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInDocument"
              },
              {
                "type": "null"
              }
            ],
            "description": "The document the post attaches (a PDF or slides shown as pages), whose first pages are in media; null when none."
          },
          "hidden_image_count": {
            "description": "How many more images the post has beyond those in media (LinkedIn shows the rest only to signed-in members); null when it shows them all.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_author_influencer": {
            "description": "LinkedIn shows its Influencer badge beside the author's name.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_edited": {
            "description": "LinkedIn marks the post as edited; null on an article.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "link": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInLink"
              },
              {
                "type": "null"
              }
            ],
            "description": "The link card the post shares (an article, an external video, a live event); null when none."
          },
          "modified_at": {
            "description": "When an article was last edited, RFC 3339 UTC; null on a post.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "more_articles": {
            "description": "An article's More articles by its author, in LinkedIn's order; [] on a post.",
            "items": {
              "$ref": "#/components/schemas/LinkedInArticleCard"
            },
            "type": "array"
          },
          "repost_activity_id": {
            "description": "The activity the link named when it was a repost without commentary: the page shows the original post, which is what this answer describes (id, author, text, published_at are the original's). Null otherwise.",
            "type": [
              "string",
              "null"
            ]
          },
          "reshared_post": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInResharedPost"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post this one reshares with commentary; null when it reshares none."
          },
          "top_comments": {
            "description": "The comments LinkedIn shows on the post's page logged out (about ten at most), in its order; [] when none.",
            "items": {
              "$ref": "#/components/schemas/LinkedInPostComment"
            },
            "type": "array"
          }
        },
        "required": [
          "content_urn",
          "author_headline",
          "author_follower_count",
          "is_author_influencer",
          "is_edited",
          "repost_activity_id",
          "link",
          "document",
          "hidden_image_count",
          "reshared_post",
          "top_comments",
          "modified_at",
          "more_articles"
        ],
        "type": "object"
      },
      "LinkedInProfileSpecific": {
        "properties": {
          "affiliated_pages": {
            "description": "Pages LinkedIn shows as affiliated with this one (its showcase pages, its parent or subsidiaries); [] when it shows none.",
            "items": {
              "$ref": "#/components/schemas/LinkedInPageRef"
            },
            "type": "array"
          },
          "certifications": {
            "description": "The member's licenses and certifications, as their public profile lists them; [] when it lists none, and for a Page.",
            "items": {
              "$ref": "#/components/schemas/LinkedInCertification"
            },
            "type": "array"
          },
          "company_size": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Range"
              },
              {
                "type": "null"
              }
            ],
            "description": "The Page's company size, the bucket of employees it declares (10,001+ is a lower bound with no upper bound); null when not shown."
          },
          "connection_count": {
            "description": "The member's connections; LinkedIn shows any count above 500 as 500+, which is 500 here and listed in approximate_fields. Null when not shown, and for a Page.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "courses": {
            "description": "The courses the member lists; [] when they list none, and for a Page.",
            "items": {
              "$ref": "#/components/schemas/LinkedInCourse"
            },
            "type": "array"
          },
          "education": {
            "description": "The member's education, as their public profile lists it. Where LinkedIn hides the list from logged-out visitors, the school it still names, with degree null; [] when it names none.",
            "items": {
              "$ref": "#/components/schemas/LinkedInEducation"
            },
            "type": "array"
          },
          "employee_count": {
            "description": "Members who list the organization as their employer, exact as LinkedIn counts them; null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "employees": {
            "description": "Members LinkedIn shows as working at the organization (the few its Page names logged out); [] when it names none.",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "experience": {
            "description": "The member's positions, as their public profile lists them (current first, then past). Where LinkedIn hides the list from logged-out visitors, the current organization it still names, with title null; [] when it names none.",
            "items": {
              "$ref": "#/components/schemas/LinkedInPosition"
            },
            "type": "array"
          },
          "founded_year": {
            "description": "The year the organization was founded, as its Page states it; null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "headline": {
            "description": "The member's headline, the line under their name; null when they have none, and for a Page.",
            "type": [
              "string",
              "null"
            ]
          },
          "headquarters": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInAddress"
              },
              {
                "type": "null"
              }
            ],
            "description": "The Page's headquarters address; null when not shown. location is its city and region as one line."
          },
          "honors": {
            "description": "The member's honors and awards, as their public profile lists them; [] when it lists none, and for a Page.",
            "items": {
              "$ref": "#/components/schemas/LinkedInHonor"
            },
            "type": "array"
          },
          "is_creator": {
            "description": "True when LinkedIn marks the member as a creator (creator mode); null for a Page.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_hiring": {
            "description": "True when the member shows LinkedIn's Hiring frame, false when they don't; null when unknown (as is_open_to_work) and for a Page.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_influencer": {
            "description": "True when LinkedIn marks the member as an influencer (its Top Voice badge beside the name); null for a Page.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_open_to_work": {
            "description": "True when the member shows LinkedIn's Open to Work frame, false when they don't; null when unknown (LinkedIn's logged-out page doesn't show it, a data partner's copy does: meta.source vendor) and for a Page.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "kind": {
            "description": "What the account is on LinkedIn: a company's Page (linkedin.com/company/…), a school's (/school/…), a showcase page, a company's page for one brand or product (/showcase/…), or a member, a person (/in/…). New values may be added; treat unknown values as other.",
            "enum": [
              "company",
              "school",
              "showcase",
              "member",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "languages": {
            "description": "The languages the member lists, with the proficiency they state; [] when they list none, and for a Page.",
            "items": {
              "$ref": "#/components/schemas/LinkedInLanguage"
            },
            "type": "array"
          },
          "locations": {
            "description": "The organization's locations as its Page lists them, the primary one first; [] when it lists none.",
            "items": {
              "$ref": "#/components/schemas/LinkedInLocation"
            },
            "type": "array"
          },
          "organization_type": {
            "description": "The Page's organization type as LinkedIn shows it (Public Company, Privately Held, Nonprofit, Educational, Government Agency, Self-Employed, Partnership); null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "organizations": {
            "description": "The organizations the member lists (associations and memberships, not employers); [] when they list none, and for a Page.",
            "items": {
              "$ref": "#/components/schemas/LinkedInOrganization"
            },
            "type": "array"
          },
          "patents": {
            "description": "The member's patents, as their public profile lists them; [] when it lists none, and for a Page.",
            "items": {
              "$ref": "#/components/schemas/LinkedInPatent"
            },
            "type": "array"
          },
          "projects": {
            "description": "The member's projects, as their public profile lists them; [] when it lists none, and for a Page.",
            "items": {
              "$ref": "#/components/schemas/LinkedInProject"
            },
            "type": "array"
          },
          "publications": {
            "description": "The member's publications, as their public profile lists them; [] when it lists none, and for a Page.",
            "items": {
              "$ref": "#/components/schemas/LinkedInPublication"
            },
            "type": "array"
          },
          "recommendation_count": {
            "description": "How many people have recommended the member, as LinkedIn counts them; null when not shown, and for a Page.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "recommendations": {
            "description": "Recommendations the member received, the ones LinkedIn shows logged out (a few of recommendation_count); [] when it shows none, and for a Page.",
            "items": {
              "$ref": "#/components/schemas/LinkedInRecommendation"
            },
            "type": "array"
          },
          "similar_pages": {
            "description": "Pages LinkedIn shows as similar to this one; [] when it shows none.",
            "items": {
              "$ref": "#/components/schemas/LinkedInPageRef"
            },
            "type": "array"
          },
          "similar_profiles": {
            "description": "Members LinkedIn shows as similar to this one (its People also viewed); [] when it shows none, and for a Page.",
            "items": {
              "$ref": "#/components/schemas/LinkedInMemberRef"
            },
            "type": "array"
          },
          "skills": {
            "description": "The skills the member lists, in their order; [] when they list none, and for a Page.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "specialties": {
            "description": "The Page's specialties, in its order; [] when it lists none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "tagline": {
            "description": "The Page's tagline, the line under its name; null when it has none, and for a member.",
            "type": [
              "string",
              "null"
            ]
          },
          "volunteering": {
            "description": "The member's volunteer experience, as their public profile lists it; [] when it lists none, and for a Page.",
            "items": {
              "$ref": "#/components/schemas/LinkedInVolunteering"
            },
            "type": "array"
          }
        },
        "required": [
          "kind",
          "tagline",
          "organization_type",
          "company_size",
          "employee_count",
          "founded_year",
          "specialties",
          "headquarters",
          "locations",
          "affiliated_pages",
          "similar_pages",
          "employees",
          "headline",
          "connection_count",
          "is_influencer",
          "experience",
          "education",
          "is_creator",
          "is_open_to_work",
          "is_hiring",
          "volunteering",
          "projects",
          "publications",
          "honors",
          "certifications",
          "patents",
          "courses",
          "organizations",
          "languages",
          "skills",
          "recommendations",
          "recommendation_count",
          "similar_profiles"
        ],
        "type": "object"
      },
      "LinkedInProject": {
        "properties": {
          "contributors": {
            "description": "The other members LinkedIn lists as its creators; [] when it lists none.",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "description": {
            "description": "The member's description of it; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "ended_on": {
            "description": "When it ended, a year or a month; null while ongoing or when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "started_on": {
            "description": "When it started, a year or a month; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The project's name.",
            "type": "string"
          },
          "url": {
            "description": "The project's link; null when it has none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "title",
          "url",
          "started_on",
          "ended_on",
          "description",
          "contributors"
        ],
        "type": "object"
      },
      "LinkedInPublication": {
        "properties": {
          "authors": {
            "description": "The other members LinkedIn lists as its authors; [] when it lists none.",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "description": {
            "description": "The member's description of it; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "published_on": {
            "description": "When it was published: a day (2025-01-28), a month or a year; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "publisher": {
            "description": "The publisher, as written; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The publication's title.",
            "type": "string"
          },
          "url": {
            "description": "The publication's link; null when it has none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "title",
          "url",
          "publisher",
          "published_on",
          "description",
          "authors"
        ],
        "type": "object"
      },
      "LinkedInRecommendation": {
        "properties": {
          "recommender": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The member who wrote it; null when LinkedIn does not name them."
          },
          "text": {
            "description": "The recommendation's text, as shown.",
            "type": "string"
          }
        },
        "required": [
          "recommender",
          "text"
        ],
        "type": "object"
      },
      "LinkedInResharedPost": {
        "properties": {
          "author": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "Its author."
          },
          "id": {
            "description": "Its activity ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "media": {
            "description": "Its attachments; [] for a text post.",
            "items": {
              "$ref": "#/components/schemas/Media"
            },
            "type": "array"
          },
          "published_at": {
            "description": "When it went public, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "text": {
            "description": "Its text.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Its canonical link.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "author",
          "text",
          "published_at",
          "media"
        ],
        "type": "object"
      },
      "LinkedInVolunteering": {
        "properties": {
          "cause": {
            "description": "The cause, as LinkedIn names it (Economic Empowerment, Health, Education); null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "description": "The member's description of it; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "ended_on": {
            "description": "When it ended, a year or a month; null while current (is_current) or when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_current": {
            "description": "True for a role LinkedIn shows as ongoing (to Present); false otherwise, including when no dates are shown.",
            "type": "boolean"
          },
          "organization": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The organization, with its Page's link when it has one; null when not shown."
          },
          "role": {
            "description": "The member's role; null when not shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "started_on": {
            "description": "When it started, a year (2015) or a month (2015-03); null when not shown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "role",
          "organization",
          "cause",
          "started_on",
          "ended_on",
          "is_current",
          "description"
        ],
        "type": "object"
      },
      "LinkedInWebResultSpecific": {
        "properties": {
          "company": {
            "description": "A member's current employer, as the index's snippet says it; null when it does not, and for a Page.",
            "type": [
              "string",
              "null"
            ]
          },
          "connection_count": {
            "description": "A member's connections as the index's snippet states them (LinkedIn shows any count above 500 as 500+, which is 500 here); null when it does not, and for a Page.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "headline": {
            "description": "What the index's title says of a member after their name: their headline, or where LinkedIn hides it their current employer, school or place (often cut short); null when it says none, and for a Page.",
            "type": [
              "string",
              "null"
            ]
          },
          "kind": {
            "description": "What the account is on LinkedIn, as its link says: a company's Page, a school's, a showcase page, or a member. Null when unknown. New values may be added; treat unknown values as unknown.",
            "enum": [
              "company",
              "school",
              "showcase",
              "member",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "description": "Where a member is, as the index's snippet or title says it; null when it does not, and for a Page.",
            "type": [
              "string",
              "null"
            ]
          },
          "school": {
            "description": "The school a member's profile shows first, as the index's snippet says it; null when it does not, and for a Page.",
            "type": [
              "string",
              "null"
            ]
          },
          "tagline": {
            "description": "A Page's tagline as the index's snippet quotes it; null when it quotes none, and for a member.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "kind",
          "tagline",
          "headline",
          "location",
          "company",
          "school",
          "connection_count"
        ],
        "type": "object"
      },
      "LinkedinAdResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Ad"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "LinkedinPostResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "LinkedinProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "LinkedinSearch_adsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 24), most recently started first with sort=newest, earliest started first with sort=oldest.",
            "items": {
              "$ref": "#/components/schemas/Ad"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "LinkedinSearch_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "LinkedinSearch_profilesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "LinkmeFeaturedLink": {
        "properties": {
          "description": {
            "description": "The text under the label; a music link's artist; null if none.",
            "type": [
              "string",
              "null"
            ]
          },
          "group": {
            "description": "The title of the carousel the card belongs to; null outside a carousel or for one without a title.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "The link's ID on Linkme.",
            "type": "string"
          },
          "image_url": {
            "description": "The link's thumbnail; null if none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "is_adult": {
            "description": "True when Linkme marks the link as adult content and shows a notice before opening it.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "platform": {
            "description": "The site Linkme recognizes the link as (instagram, spotify, opentable, …); link for any other.",
            "type": [
              "string",
              "null"
            ]
          },
          "platforms": {
            "description": "The destinations a music link offers in its menu; [] for any other link.",
            "items": {
              "$ref": "#/components/schemas/LinkmeLinkPlatform"
            },
            "type": "array"
          },
          "section": {
            "description": "The heading the link sits under on the page; null if none.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The link's label.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Where the link goes; null only for an adult link whose target could not be read (the list is then in approximate_fields) or a music link, which has platforms instead.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "description",
          "url",
          "image_url",
          "platform",
          "section",
          "group",
          "is_adult",
          "platforms"
        ],
        "type": "object"
      },
      "LinkmeLinkPlatform": {
        "properties": {
          "name": {
            "description": "The destination's label (Spotify, Apple Music, …).",
            "type": "string"
          },
          "url": {
            "description": "The release on that destination.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "name",
          "url"
        ],
        "type": "object"
      },
      "LinkmeProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile",
            "description": "In Linkme's words: `metrics.follower_count` is total followers."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "LinkmeProfileSpecific": {
        "properties": {
          "emails": {
            "description": "Email addresses the page publishes in its contact block; [] if none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "featured_links": {
            "description": "The page's list of link buttons and cards, in page order, with a carousel's cards in place of the carousel and without section headings, which each entry names instead; [] if none.",
            "items": {
              "$ref": "#/components/schemas/LinkmeFeaturedLink"
            },
            "type": "array"
          },
          "is_adult": {
            "description": "True when the page opens behind an age gate: a notice to continue past, or a birth date to type.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "link_count": {
            "description": "How many entries Linkme counts in the page's link list, section headings and carousels each counting as one.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "linkme_connection_count": {
            "description": "The part of metrics.follower_count Linkme counts itself, which the page's followers sheet lists as Links on the account's own Linkme row; not the links on the page (link_count is). Null when the account hid its total, or on a private page.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "locations": {
            "description": "Street addresses or places the page publishes in its contact block, as written; [] if none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "logo_url": {
            "description": "The brand logo the page uploaded; null if none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "network_follower_count": {
            "description": "The part of metrics.follower_count that comes from the networks the account connected to Linkme. Null when it has none (no network connected), when the account hid its total, or on a private page.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "phones": {
            "description": "Phone numbers the page publishes in its contact block, as written; [] if none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "profile_visit_count": {
            "description": "How many visits Linkme counts for the page, as Linkme rounds it from a thousand up: then listed in approximate_fields.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "social_links": {
            "description": "The page's row of social icons, in order; [] if none.",
            "items": {
              "$ref": "#/components/schemas/LinkmeSocialLink"
            },
            "type": "array"
          },
          "updated_at": {
            "description": "When the account last changed, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "emails",
          "phones",
          "locations",
          "social_links",
          "featured_links",
          "link_count",
          "profile_visit_count",
          "network_follower_count",
          "linkme_connection_count",
          "is_adult",
          "logo_url",
          "updated_at"
        ],
        "type": "object"
      },
      "LinkmeSocialLink": {
        "properties": {
          "follower_count": {
            "description": "The account's followers on that platform, as Linkme last read them; null for a link the account did not connect.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "handle": {
            "description": "The name or ID Linkme stores for the icon, usually the account's username on that platform.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_adult": {
            "description": "True when Linkme marks the link as adult content and shows a notice before opening it.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "platform": {
            "description": "The icon's name as Linkme labels it (Instagram, Tiktok, Youtube, OF, Customlink, …).",
            "type": "string"
          },
          "url": {
            "description": "Where the icon links to; null when it holds no link, only a name to copy (an Xbox gamertag, a Zelle name), which handle then gives.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "platform",
          "url",
          "handle",
          "follower_count",
          "is_adult"
        ],
        "type": "object"
      },
      "LinktreeLink": {
        "properties": {
          "gates": {
            "description": "What a visitor passes before following it: sensitive_content and age are click-throughs, anything else (passcode, password, nft, subscribed, wall) is a lock. [] when it opens directly.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "group_id": {
            "description": "The ID of the GROUP block it sits in; null at the top level of the page.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Linktree's ID of the link.",
            "type": "string"
          },
          "position": {
            "description": "Its order within its group, or on the page when it has no group: lower comes first, and gaps are normal (links lists blocks in page order already).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "The block's image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The label shown on the page.",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "Linktree's type of the block (CLASSIC, GROUP, HEADER, YOUTUBE_VIDEO, SPOTIFY_ALBUM, COMMERCE_PRODUCT, …). New values appear as Linktree adds them.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Destination; null for a block with no http(s) one (GROUP, HEADER, an EMAIL block's mailto:) and for a link behind a lock.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "title",
          "url",
          "thumbnail_url",
          "position",
          "group_id",
          "gates"
        ],
        "type": "object"
      },
      "LinktreeProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "LinktreeProfileSpecific": {
        "properties": {
          "badges": {
            "description": "The badges on the page, as Linktree names them (VERIFICATION_TICK, VERIFIED_AND_NOTABLE_TICK).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "content_warning": {
            "description": "The warning a visitor accepts before the page shows, as Linktree names it (generic, eighteenPlus, twentyOnePlus, twentyFivePlus, moderated); null when there is none.",
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "description": "The email address the page lists, on its email icon or an email link.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_sensitive": {
            "description": "True when Linktree marks the page as having sensitive content.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "link_platforms": {
            "description": "The platforms Linktree lists the account as being on, as it names them (TikTok, Instagram, X, …).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "links": {
            "description": "Every block on the page in page order, with its type and group, including headers and groups that have no URL. external_links holds the same destinations without the structure.",
            "items": {
              "$ref": "#/components/schemas/LinktreeLink"
            },
            "type": "array"
          },
          "social_links": {
            "description": "The page's social icons.",
            "items": {
              "$ref": "#/components/schemas/LinktreeSocialLink"
            },
            "type": "array"
          },
          "timezone": {
            "description": "The account's IANA time zone (America/New_York).",
            "type": [
              "string",
              "null"
            ]
          },
          "updated_at": {
            "description": "When the page was last changed, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "verticals": {
            "description": "The industries Linktree files the account under, as its slugs (music, fashion-beauty, …).",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "links",
          "social_links",
          "email",
          "timezone",
          "updated_at",
          "verticals",
          "link_platforms",
          "badges",
          "is_sensitive",
          "content_warning"
        ],
        "type": "object"
      },
      "LinktreeSocialLink": {
        "properties": {
          "platform": {
            "description": "Which icon, as Linktree's type in lower case (instagram, tiktok, x, email_address, …). New values appear as Linktree adds them.",
            "type": "string"
          },
          "url": {
            "description": "Destination: usually an https link, mailto: for an email icon.",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "url"
        ],
        "type": "object"
      },
      "Live": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform or parsed from display text. A list path means the list may be incomplete. [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "category": {
            "description": "The topic or game the broadcast is filed under, as the platform names it.",
            "type": [
              "string",
              "null"
            ]
          },
          "ended_at": {
            "description": "When it went off air, RFC 3339 UTC; null while live or scheduled, and when the platform does not say.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "host": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "The broadcasting account."
          },
          "id": {
            "description": "Platform-native ID of the broadcast (string; TikTok room ID, YouTube video ID).",
            "type": "string"
          },
          "metrics": {
            "$ref": "#/components/schemas/LiveMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "platform": {
            "description": "Platform ID (tiktok, youtube, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/LivePlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "post_id": {
            "description": "ID of the post the platform keeps the broadcast as (equals post.id: a YouTube or Rumble video); null when it keeps none (TikTok LIVE) or none yet.",
            "type": [
              "string",
              "null"
            ]
          },
          "scheduled_start_at": {
            "description": "When a scheduled broadcast is due to start, RFC 3339 UTC; null when none was announced.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "started_at": {
            "description": "When the broadcast went on air, RFC 3339 UTC; null while scheduled or when not shown.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "description": "live: on air now; scheduled: announced, not started; ended: over. New values may be added; treat an unknown value as not live.",
            "enum": [
              "live",
              "scheduled",
              "ended"
            ],
            "type": "string"
          },
          "streams": {
            "description": "Playback links of the broadcast while live, one per rendition and format, best first; [] when not live or when the platform's links only work from SocialTap's network (YouTube).",
            "items": {
              "$ref": "#/components/schemas/LiveStream"
            },
            "type": "array"
          },
          "text": {
            "description": "Description as plain text; null where the platform has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "Cover or preview image URL. Platform CDN URLs can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The broadcast's title as the host set it.",
            "type": [
              "string",
              "null"
            ]
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Public page of the broadcast (TikTok: the host's LIVE page, tiktok.com/@<username>/live).",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "url",
          "status",
          "title",
          "text",
          "category",
          "host",
          "started_at",
          "ended_at",
          "scheduled_start_at",
          "thumbnail_url",
          "post_id",
          "streams",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "LiveMetrics": {
        "properties": {
          "concurrent_viewer_count": {
            "description": "People watching now; null when not live or not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "like_count": {
            "description": "Likes or hearts; null when hidden or not exposed.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "view_count": {
            "description": "Cumulative views since the broadcast began (TikTok counts entries into the room).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "concurrent_viewer_count",
          "view_count",
          "like_count"
        ],
        "type": "object"
      },
      "LivePlatformSpecific": {
        "properties": {
          "tiktok": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokLiveSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A TikTok LIVE room's own fields."
          },
          "twitch": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TwitchLiveSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Twitch broadcast's own fields."
          }
        },
        "type": "object"
      },
      "LiveStream": {
        "properties": {
          "bitrate_kbps": {
            "description": "Target bitrate in kbit/s, when the platform states it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "expires_at": {
            "description": "When url stops working, RFC 3339 UTC, read from the platform's signed URL; null when unknown.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "format": {
            "description": "Delivery format of url: hls (an .m3u8 playlist), dash (an .mpd manifest, TikTok's CMAF) or flv (HTTP-FLV). New values may be added; treat unknown values as other.",
            "enum": [
              "hls",
              "dash",
              "flv"
            ],
            "type": "string"
          },
          "height": {
            "description": "Height in pixels; null for audio-only or when not stated.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_audio_only": {
            "description": "The rendition carries sound only.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "quality": {
            "description": "The platform's label for the rendition (Original, 1080p60, 720p, …).",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Playback URL, signed and expiring: see expires_at.",
            "format": "uri",
            "type": "string"
          },
          "video_codec": {
            "description": "Video codec, lowercase (h264, h265); null for audio-only or when not stated.",
            "type": [
              "string",
              "null"
            ]
          },
          "width": {
            "description": "Width in pixels; null for audio-only or when not stated.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "quality",
          "format",
          "url",
          "expires_at",
          "width",
          "height",
          "video_codec",
          "bitrate_kbps",
          "is_audio_only"
        ],
        "type": "object"
      },
      "Media": {
        "properties": {
          "alt_text": {
            "description": "Accessibility text provided by the author or platform.",
            "type": [
              "string",
              "null"
            ]
          },
          "duration_ms": {
            "description": "Duration in milliseconds (video and audio only).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "expires_at": {
            "description": "When url stops working, RFC 3339 UTC, read from the platform's signed URL; null when unknown or when it does not expire.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "height": {
            "description": "Height in pixels.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "Poster or preview image URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "Kind of file. New values may be added; treat unknown values as other.",
            "enum": [
              "image",
              "video",
              "audio",
              "gif"
            ],
            "type": "string"
          },
          "url": {
            "description": "Direct file URL; null when the platform withholds it, or when the link would only work from SocialTap's network or with a login. Often signed and expiring: see expires_at.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "width": {
            "description": "Width in pixels.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "type",
          "url",
          "expires_at",
          "thumbnail_url",
          "width",
          "height",
          "duration_ms",
          "alt_text"
        ],
        "type": "object"
      },
      "MoneyRange": {
        "properties": {
          "currency": {
            "description": "ISO 4217 currency code, uppercase (USD).",
            "type": "string"
          },
          "lower_bound": {
            "description": "Inclusive lower bound, in whole units of currency.",
            "format": "int64",
            "type": "integer"
          },
          "upper_bound": {
            "description": "Inclusive upper bound in whole units of currency; null when open-ended.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "lower_bound",
          "upper_bound",
          "currency"
        ],
        "type": "object"
      },
      "Offer": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform or parsed from display text (a seller rating in half stars, a date-only delivery estimate). [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "availability": {
            "description": "in_stock: can be bought now; out_of_stock: sold out for now; pre_order: ships later. Null when the platform does not say. New values may be added; treat unknown values as null.",
            "enum": [
              "in_stock",
              "out_of_stock",
              "pre_order",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "condition": {
            "description": "Item condition, coarse: new, used (any grade) or refurbished; null when the platform does not say. The platform's own grade is condition_label. New values may be added; treat unknown values as used.",
            "enum": [
              "new",
              "used",
              "refurbished",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "condition_label": {
            "description": "The condition as the platform labels it (Used - Like New, Pre-Owned: Good, Renewed).",
            "type": [
              "string",
              "null"
            ]
          },
          "country_code": {
            "description": "ISO 3166-1 alpha-2 market the offer is in; its prices, availability and delivery are that market's.",
            "type": [
              "string",
              "null"
            ]
          },
          "currency": {
            "description": "ISO 4217 code of every amount of this offer (USD); null when no amount is shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "The offer's ID: the platform's own where it is stable across fetches, else derived from the product, the seller and the condition (B0FQFB8FMG:ALAQLAKJ574UN:new), with ~2, ~3 for a seller's further offers in one condition, counted across the list's pages in the platform's order. A derived ID is stable while the seller's offers in that condition keep their order; two of them can swap IDs when their order changes.",
            "type": "string"
          },
          "is_featured": {
            "description": "The offer the product page shows by default (the buy box); at most one offer of a product is. Null where the platform features none.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/OfferMetrics",
            "description": "Counts at fetch time; null = not shown, 0 = zero."
          },
          "original_price": {
            "description": "Price before the discount (the struck-through list or earlier price), in major units of currency; null when the offer shows none.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "platform": {
            "description": "Platform ID (amazon, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/OfferPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "price": {
            "description": "The offer's price in major units of currency (58.47), discounts applied; shipping and tax excluded. 0 = free; null when not shown.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "product_id": {
            "description": "ID of the product offered (equals product.id of the platform's product endpoints).",
            "type": "string"
          },
          "seller": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "The seller (a shop on the platform, or a merchant's site on a comparison platform); fields null when not shown."
          },
          "seller_rating": {
            "description": "The seller's average rating out of 5 (metrics.seller_rating_count ratings behind it), as the platform shows it (rounded ones in approximate_fields); null when the seller is unrated or the platform does not show it.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "shipping": {
            "$ref": "#/components/schemas/OfferShipping",
            "description": "Delivery terms of this offer; each null when not shown."
          },
          "title": {
            "description": "The seller's own title for the product, where offers carry one (an eBay listing's, a shop's on Google Shopping); null where every offer shares the product's title.",
            "type": [
              "string",
              "null"
            ]
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none; null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "The offer's own page (the merchant's page, the listing, or the product page with this seller selected); null when the platform has none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "platform",
          "id",
          "product_id",
          "url",
          "title",
          "seller",
          "price",
          "original_price",
          "currency",
          "condition",
          "condition_label",
          "availability",
          "is_featured",
          "seller_rating",
          "shipping",
          "country_code",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "OfferMetrics": {
        "properties": {
          "seller_rating_count": {
            "description": "Ratings behind seller_rating, as the platform counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "seller_rating_count"
        ],
        "type": "object"
      },
      "OfferPlatformSpecific": {
        "properties": {
          "amazon": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AmazonOfferSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Amazon offer's own fields."
          }
        },
        "type": "object"
      },
      "OfferShipping": {
        "properties": {
          "earliest_delivery_at": {
            "description": "First day of the standard delivery estimate, as that date at 00:00:00Z (date-only: approximate_fields); equal to latest_delivery_at for a one-day estimate; null when the platform gives no start.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "fee": {
            "description": "Standard shipping fee of this item alone, in major units of the offer's currency; 0 = free shipping; null when it depends on the order (free over a threshold) or is not shown.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "is_offered": {
            "description": "The seller ships this offer (false: local pickup only); null when not shown.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "latest_delivery_at": {
            "description": "Last day of the standard delivery estimate, as that date at 00:00:00Z (date-only: approximate_fields); null when the platform gives no estimate.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "is_offered",
          "fee",
          "earliest_delivery_at",
          "latest_delivery_at"
        ],
        "type": "object"
      },
      "PageInfo": {
        "properties": {
          "end_reason": {
            "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
            "enum": [
              "end",
              "platform_limit",
              "max_pages",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "has_more": {
            "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
            "type": "boolean"
          },
          "next_cursor": {
            "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
            "type": [
              "string",
              "null"
            ]
          },
          "next_cursor_expires_at": {
            "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "has_more",
          "next_cursor",
          "next_cursor_expires_at",
          "end_reason"
        ],
        "type": "object"
      },
      "PillarChannel": {
        "properties": {
          "channel_name": {
            "description": "The account's name or ID on that service, as Pillar stores it.",
            "type": "string"
          },
          "follower_count": {
            "description": "Its followers or subscribers, as Pillar last read them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "platform": {
            "description": "The service, in lowercase (instagram, tiktok, youtube, twitter, facebook, twitch, snapchat).",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "channel_name",
          "follower_count"
        ],
        "type": "object"
      },
      "PillarLink": {
        "properties": {
          "click_count": {
            "description": "How many times the link was clicked, as Pillar counts it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "description": {
            "description": "The line under the title.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Pillar's ID of the link.",
            "type": "string"
          },
          "title": {
            "description": "The link's title, as shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Where the link goes.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "id",
          "title",
          "description",
          "url",
          "click_count"
        ],
        "type": "object"
      },
      "PillarPageResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile",
            "description": "In Pillar's words: `metrics.follower_count` is audience."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "PillarProduct": {
        "properties": {
          "currency": {
            "description": "The price's ISO 4217 currency.",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "description": "The item's short description.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Pillar's ID of the item.",
            "type": "string"
          },
          "image_url": {
            "description": "The item's image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "price": {
            "description": "The price, in currency; null when the page does not show one.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "title": {
            "description": "The item's name.",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "product links to another store; digital_product, course, experience and fan_request are sold on Pillar itself. New values may be added.",
            "enum": [
              "product",
              "digital_product",
              "course",
              "experience",
              "fan_request"
            ],
            "type": "string"
          },
          "url": {
            "description": "Where to buy it: the store's link for a product, the Pillar checkout otherwise.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "title",
          "description",
          "url",
          "image_url",
          "price",
          "currency"
        ],
        "type": "object"
      },
      "PillarProfileSpecific": {
        "properties": {
          "audience": {
            "description": "The connected accounts the page shows follower counts for: [] if it shows none.",
            "items": {
              "$ref": "#/components/schemas/PillarChannel"
            },
            "type": "array"
          },
          "contact_email": {
            "description": "The contact email address on the creator's Pillar account; null when the page hides its email icon.",
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "description": "The email address the page shows among its social icons: the icon's own, else the contact email; null when it has none or hides it.",
            "type": [
              "string",
              "null"
            ]
          },
          "first_name": {
            "description": "The first name on the Pillar account.",
            "type": [
              "string",
              "null"
            ]
          },
          "full_name": {
            "description": "The full name on the Pillar account, which can differ from display_name.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_claimed": {
            "description": "False for a page Pillar set up that its creator has not claimed yet.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "last_name": {
            "description": "The last name on the Pillar account: the full name after the first name; null when it does not start with it.",
            "type": [
              "string",
              "null"
            ]
          },
          "links": {
            "description": "The links the page shows, in page order, with their click counts: [] if none.",
            "items": {
              "$ref": "#/components/schemas/PillarLink"
            },
            "type": "array"
          },
          "products": {
            "description": "What the page sells or recommends, in page order: [] if nothing.",
            "items": {
              "$ref": "#/components/schemas/PillarProduct"
            },
            "type": "array"
          },
          "socials": {
            "description": "The social accounts the page shows as icons: [] if none.",
            "items": {
              "$ref": "#/components/schemas/PillarSocial"
            },
            "type": "array"
          },
          "videos": {
            "description": "The videos the page features, in page order: [] if none.",
            "items": {
              "$ref": "#/components/schemas/PillarVideo"
            },
            "type": "array"
          }
        },
        "required": [
          "first_name",
          "last_name",
          "full_name",
          "email",
          "contact_email",
          "is_claimed",
          "socials",
          "links",
          "products",
          "videos",
          "audience"
        ],
        "type": "object"
      },
      "PillarSocial": {
        "properties": {
          "platform": {
            "description": "The service, in lowercase, as Pillar names it (instagram, tiktok, spotify, apple_app_store, …).",
            "type": "string"
          },
          "url": {
            "description": "The link behind the icon.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "url"
        ],
        "type": "object"
      },
      "PillarVideo": {
        "properties": {
          "description": {
            "description": "The video's description on the page.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Pillar's ID of the video.",
            "type": "string"
          },
          "title": {
            "description": "The video's title on the page.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The video's link.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "id",
          "title",
          "description",
          "url"
        ],
        "type": "object"
      },
      "PinterestBoardRef": {
        "properties": {
          "id": {
            "description": "The board's ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The board's name.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The board's link.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "url"
        ],
        "type": "object"
      },
      "PinterestBoardResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Playlist"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "PinterestBoard_pinsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), Pinterest's order for logged-out visitors: mostly the latest saved first, with a few pins it picks moved to the top. In Pinterest's words: `metrics.like_count` is reactions, `metrics.save_count` is saves.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "PinterestBoardsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the order the account's profile shows its boards in: its own arrangement (A to Z, or one it set by hand), else the boards saved to most recently first.",
            "items": {
              "$ref": "#/components/schemas/Playlist"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "PinterestPinResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post",
            "description": "In Pinterest's words: `metrics.like_count` is reactions, `metrics.save_count` is saves."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "PinterestPinsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 25), newest first. In Pinterest's words: `metrics.like_count` is reactions, `metrics.save_count` is saves.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "PinterestPlaylistSpecific": {
        "properties": {
          "board": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PinterestBoardRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "For a section, the board it is part of; null on a board."
          },
          "collaborator_count": {
            "description": "Accounts other than its owner that can save pins to the board, exact; 0 on a board only its owner saves to.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "collaborators": {
            "description": "The accounts other than its owner that can save pins to the board, as Pinterest lists them; [] when none.",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "created_at": {
            "description": "When the board was created, RFC 3339 UTC; null on a section and when the source does not state it.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "follower_count": {
            "description": "Accounts following the board, exact; null on a section, which has no followers of its own.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "interests": {
            "description": "The interests Pinterest relates the board to, each an ideas page of its own, in its order; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "privacy": {
            "description": "public, or protected: a board Pinterest keeps off its owner's profile and out of search engines but shows anyone with its link (a shop's catalog of products). New values may be added.",
            "type": [
              "string",
              "null"
            ]
          },
          "section_count": {
            "description": "Sections the board is divided into; 0 when none, null on a section.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "follower_count",
          "created_at",
          "privacy",
          "collaborator_count",
          "collaborators",
          "section_count",
          "interests",
          "board"
        ],
        "type": "object"
      },
      "PinterestPostSpecific": {
        "properties": {
          "author_follower_count": {
            "description": "The pinner's exact follower count; null when the source does not state it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "board": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PinterestBoardRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The board the pin is saved to."
          },
          "caption_languages": {
            "description": "The languages of the captions Pinterest has for the pin's video (en-us, …), as BCP-47 tags; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "domain": {
            "description": "The linked site's domain as Pinterest shows it (tastemade.com); null for a pin that links nowhere.",
            "type": [
              "string",
              "null"
            ]
          },
          "dominant_color": {
            "description": "The picture's dominant color, as #rrggbb.",
            "type": [
              "string",
              "null"
            ]
          },
          "interests": {
            "description": "The interests Pinterest files the pin under, each an ideas page of its own, in its order; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "is_ad": {
            "description": "The pin runs as an ad (a Promoted pin).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_author_verified_merchant": {
            "description": "Whether the pinner is a Pinterest verified merchant (a shop Pinterest checked); null when the source does not state it.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_repin": {
            "description": "The pin is a save (repin) of another account's pin.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "link_url": {
            "description": "The page the pin links to (its destination); null for a pin saved without one.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "original_pinner": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The account that first saved this picture or video to Pinterest (its uploader, for a pin made on Pinterest); null when Pinterest names none. author is the account whose pin this is, which for a repin is another."
          },
          "repin_count": {
            "description": "Saves of this pin itself; metrics.save_count counts the saves of every pin of the same picture or video.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "rich_type": {
            "description": "The kind of page a rich pin shows details of (recipe, article, product, …); null for a pin that is no rich pin.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "link_url",
          "domain",
          "board",
          "original_pinner",
          "author_follower_count",
          "is_author_verified_merchant",
          "is_repin",
          "repin_count",
          "dominant_color",
          "rich_type",
          "interests",
          "caption_languages",
          "is_ad"
        ],
        "type": "object"
      },
      "PinterestProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile",
            "description": "In Pinterest's words: `metrics.post_count` is pins."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "PinterestProfileSpecific": {
        "properties": {
          "all_following_count": {
            "description": "Everything the account follows, as Pinterest counts it: accounts, boards and interests. metrics.following_count counts the accounts alone. Its page's \"N following\" is this minus interest_following_count (accounts and boards), so it can be more than metrics.following_count.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "interest_following_count": {
            "description": "The interests (topics) the account follows, as Pinterest counts them: part of all_following_count, and the part its page's following count leaves out.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_business_account": {
            "description": "A Pinterest business account, which brands and creators alike can have.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_verified_merchant": {
            "description": "Pinterest's verified merchant badge: a shop whose products Pinterest checked.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_website_verified": {
            "description": "True when the account proved it owns the website in external_links (Pinterest's claimed website).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "last_post_at": {
            "description": "When the account last saved a pin to one of its boards, its own or another account's, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "monthly_view_count": {
            "description": "The account's monthly views, as Pinterest counts them: how often its pins were seen over the last month. Above ten million Pinterest writes only that it is more, and this is 10000000, listed in approximate_fields; null when the account hides it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "playlist_count": {
            "description": "Boards, as Pinterest counts them for the account. Its public list of boards can hold fewer.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "playlist_count",
          "monthly_view_count",
          "all_following_count",
          "interest_following_count",
          "is_business_account",
          "is_verified_merchant",
          "is_website_verified",
          "last_post_at"
        ],
        "type": "object"
      },
      "PinterestRefinement": {
        "properties": {
          "id": {
            "description": "The narrower topic's ID.",
            "type": "string"
          },
          "label": {
            "description": "The button's text (Blue for Blue Star Nail Designs).",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "The narrower topic's full name.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The narrower topic's ideas page.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "label",
          "id",
          "name",
          "url"
        ],
        "type": "object"
      },
      "PinterestSearch_pinsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 25), Pinterest's own relevance order for the query. In Pinterest's words: `metrics.like_count` is reactions, `metrics.save_count` is saves.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "PinterestTop_trendsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), Pinterest Trends' rank for the board (1 = top).",
            "items": {
              "$ref": "#/components/schemas/Trend"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "PinterestTopicRef": {
        "properties": {
          "id": {
            "description": "The topic's ID.",
            "type": "string"
          },
          "name": {
            "description": "The topic's name as the page shows it.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The topic's ideas page.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "url"
        ],
        "type": "object"
      },
      "PinterestTopicResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Topic"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "PinterestTopicSpecific": {
        "properties": {
          "cover_image_url": {
            "description": "The picture Pinterest shows for the topic when its page is shared (one of its pins' pictures, so it changes over time); null when the page has none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "follower_count": {
            "description": "Accounts following the topic on Pinterest; null for a topic that is no interest accounts can follow (is_interest false).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_category": {
            "description": "The topic is one of Pinterest's top categories (Travel, Beauty, …), as its ideas page lists them.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_interest": {
            "description": "The topic is one of Pinterest's interests, which pins are filed under and accounts can follow; false for a page made for a search phrase.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "parent_topics": {
            "description": "The broader topics this one sits under, broadest first, as the page's breadcrumbs show them; [] for a top category.",
            "items": {
              "$ref": "#/components/schemas/PinterestTopicRef"
            },
            "type": "array"
          },
          "refinements": {
            "description": "The narrower topics the page offers as buttons above its pins, in its order; [] when none.",
            "items": {
              "$ref": "#/components/schemas/PinterestRefinement"
            },
            "type": "array"
          },
          "related_boards": {
            "description": "Boards Pinterest shows on the topic's page, in its order; [] when none.",
            "items": {
              "$ref": "#/components/schemas/PinterestBoardRef"
            },
            "type": "array"
          },
          "related_topics": {
            "description": "Related topics the page links to, in its order; [] when none.",
            "items": {
              "$ref": "#/components/schemas/PinterestTopicRef"
            },
            "type": "array"
          },
          "search_count": {
            "description": "How many searches Pinterest counts for the topic's words, as its ideas page data states it (Pinterest doesn't say over which period); null when the source does not state it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "trending_searches": {
            "description": "Searches Pinterest shows as trending for the topic, in its order; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "updated_at": {
            "description": "When Pinterest last updated the topic's page data (its counts and related topics).",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "search_count",
          "follower_count",
          "is_category",
          "is_interest",
          "updated_at",
          "parent_topics",
          "refinements",
          "related_topics",
          "trending_searches",
          "related_boards",
          "cover_image_url"
        ],
        "type": "object"
      },
      "PinterestTrendSpecific": {
        "properties": {
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country whose searches the figures count (Pinterest counts some countries together: the endpoint's notes say which).",
            "type": [
              "string",
              "null"
            ]
          },
          "history": {
            "description": "How much the term was searched each week, oldest first, relative to the series' peak (1); [] on a board that does not request the series (listed in unknown_fields).",
            "items": {
              "$ref": "#/components/schemas/TrendPoint"
            },
            "type": "array"
          },
          "market_country_codes": {
            "description": "Every country whose searches the figures count together, as ISO 3166-1 alpha-2 codes: [\"US\"] for a country Pinterest publishes a board for on its own, its group's ([\"GB\", \"IE\"] for IE) for one Pinterest counts with others. [] when unknown.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "monthly_change": {
            "description": "Change over the past month, a fraction like weekly_change, rounded by Pinterest the same way (always listed in approximate_fields); capped at 100, a lower bound then.",
            "format": "double",
            "maximum": 100,
            "minimum": -1,
            "type": [
              "number",
              "null"
            ]
          },
          "period_end_at": {
            "description": "End of the period Pinterest's figures count, exclusive (midnight UTC after its weekly data's last day), RFC 3339 UTC: Pinterest publishes weekly, a few days behind.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "search_index": {
            "description": "How much the term is searched in the table's period, relative to the table's most searched term (100).",
            "format": "int64",
            "maximum": 100,
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "seasonality": {
            "description": "How seasonal the term is, 0 to 1 (1 = searched at the same time every year), as Pinterest scores it.",
            "format": "double",
            "maximum": 1,
            "minimum": 0,
            "type": [
              "number",
              "null"
            ]
          },
          "weekly_change": {
            "description": "Change in the term's searches over the past week, a fraction (0.3 = +30 %, -0.5 = -50 %), rounded by Pinterest to one or two significant digits (always listed in approximate_fields); capped at 100 (+10,000 %), a lower bound then.",
            "format": "double",
            "maximum": 100,
            "minimum": -1,
            "type": [
              "number",
              "null"
            ]
          },
          "yearly_change": {
            "description": "Change against the same time last year, a fraction like weekly_change, rounded by Pinterest the same way (always listed in approximate_fields); capped at 100, a lower bound then.",
            "format": "double",
            "maximum": 100,
            "minimum": -1,
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "country_code",
          "market_country_codes",
          "search_index",
          "weekly_change",
          "monthly_change",
          "yearly_change",
          "seasonality",
          "period_end_at",
          "history"
        ],
        "type": "object"
      },
      "PinterestWeb_pageResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebPage",
            "description": "In Pinterest's words: `metrics.share_count` is saves."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "Place": {
        "properties": {
          "account": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The platform account that represents the place (its business account or Page); null when none is linked."
          },
          "address": {
            "description": "Address as the platform shows it: a street line on some platforms, the whole postal address or only the enclosing region on others; not normalized.",
            "type": [
              "string",
              "null"
            ]
          },
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform or parsed from display text (e.g. metrics.post_count). [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "category": {
            "description": "The platform's category label (Cafe, City, Pizza Fast Food), as shown; not normalized across platforms.",
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "description": "City or locality, as shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country of the place.",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "description": "The place's description or about text; null when none is shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native place ID (TikTok POI ID, Instagram location ID, Facebook Page ID).",
            "type": "string"
          },
          "images": {
            "description": "Pictures of the place the platform shows, in its order; each of type image. [] when none (listed in unknown_fields when the source cannot see them). Platform CDN URLs can expire within hours: see expires_at.",
            "items": {
              "$ref": "#/components/schemas/Media"
            },
            "type": "array"
          },
          "latitude": {
            "description": "WGS 84 latitude in degrees; null when the platform does not show coordinates (set together with longitude).",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "longitude": {
            "description": "WGS 84 longitude in degrees; null when the platform does not show coordinates (set together with latitude).",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/PlaceMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "name": {
            "description": "Place name as the platform shows it.",
            "type": "string"
          },
          "phone": {
            "description": "The business's public phone number, as shown; null when none is shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "platform": {
            "description": "Platform ID (tiktok, instagram, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/PlacePlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "postal_code": {
            "description": "Postal or ZIP code.",
            "type": [
              "string",
              "null"
            ]
          },
          "price_range": {
            "description": "The business's price range, 1 (inexpensive, $) to 4 (expensive, $$$$); null when the platform shows none.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "type": {
            "description": "Coarse kind: venue for one spot (a business, landmark or address), area for a region (a neighborhood, city, state or country); unknown when the platform does not say. New values may be added; treat unknown values as unknown.",
            "enum": [
              "venue",
              "area",
              "unknown"
            ],
            "type": "string"
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Canonical place page URL.",
            "format": "uri",
            "type": "string"
          },
          "website_url": {
            "description": "The place's own website.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "platform",
          "id",
          "name",
          "url",
          "type",
          "category",
          "description",
          "address",
          "city",
          "postal_code",
          "country_code",
          "latitude",
          "longitude",
          "phone",
          "website_url",
          "price_range",
          "images",
          "account",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "PlaceMetrics": {
        "properties": {
          "image_count": {
            "description": "Pictures the platform has of the place; more than the length of images when the source returns only the first ones.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "post_count": {
            "description": "Public posts tagged with the place, as the platform counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "review_count": {
            "description": "Public reviews or recommendations of the place, as the platform counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "post_count",
          "review_count",
          "image_count"
        ],
        "type": "object"
      },
      "PlacePlatformSpecific": {
        "properties": {
          "facebook": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookPlaceSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Facebook place's own fields."
          },
          "instagram": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InstagramPlaceSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Instagram location's own fields."
          },
          "tiktok": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokPlaceSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A TikTok POI's own fields."
          }
        },
        "type": "object"
      },
      "PlaceRef": {
        "properties": {
          "address": {
            "description": "Address as the platform shows it (one line, not normalized).",
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "description": "City or locality, as shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country of the place.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "The place's ID as the platform's place endpoints key it (place.id); null for a venue given as free text.",
            "type": [
              "string",
              "null"
            ]
          },
          "latitude": {
            "description": "WGS 84 latitude in degrees; null when the platform shows no coordinates (set together with longitude).",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "longitude": {
            "description": "WGS 84 longitude in degrees; null when the platform shows no coordinates (set together with latitude).",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "name": {
            "description": "The place's name as shown (a venue's name, or the text its host typed).",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The place's page URL; null for a venue given as free text.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "url",
          "address",
          "city",
          "country_code",
          "latitude",
          "longitude"
        ],
        "type": "object"
      },
      "PlaceSummary": {
        "properties": {
          "address": {
            "description": "Address as the index's text shows it; null when it does not.",
            "type": [
              "string",
              "null"
            ]
          },
          "category": {
            "description": "The platform's category label, as the index's text shows it; null when it does not.",
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "description": "City or locality, as the index's text shows it.",
            "type": [
              "string",
              "null"
            ]
          },
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country of the place.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native place ID; null until the result is filled.",
            "type": [
              "string",
              "null"
            ]
          },
          "latitude": {
            "description": "WGS 84 latitude in degrees; null unless the index's text states coordinates, until the result is filled (set together with longitude).",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "longitude": {
            "description": "WGS 84 longitude in degrees; null unless the index's text states coordinates, until the result is filled (set together with latitude).",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/PlaceMetrics",
            "description": "Counts as the index's text states them (\"12K posts\"; rounded, as old as the index's copy: see approximate_fields), or the platform's current ones once filled; null = not stated."
          },
          "name": {
            "description": "Place name as the index's title shows it; null when it shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Canonical place page URL (equals the result's url).",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "url",
          "category",
          "address",
          "city",
          "country_code",
          "latitude",
          "longitude",
          "metrics"
        ],
        "type": "object"
      },
      "Playlist": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform, date-only or parsed from display text. [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "description": {
            "description": "Description as plain text; null when it has none or the platform shows none (TikTok).",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native playlist ID (string): TikTok's playlist (mix) or collection ID, YouTube's list ID (PL…), Facebook's video list ID.",
            "type": "string"
          },
          "is_collaborative": {
            "description": "Whether people its owner invites can add to it as well (a collaborative playlist, a group board); null where the platform doesn't say.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/PlaylistMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "owner": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "The account that curates it (for a collection, the account that saved the posts, not their authors). Where a platform's curators are not accounts (Apple Music), what it states of them: a name, perhaps a page and a picture, with id and username null, and every field null when it names no one."
          },
          "platform": {
            "description": "Platform ID (tiktok, youtube, facebook, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/PlaylistPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "platform_type": {
            "description": "The platform's own label, lowercase (mix, collection, playlist, series, podcast, …).",
            "type": [
              "string",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "Cover image URL (the owner's chosen cover, else the platform's pick, often the first post's). Platform CDN URLs can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "Name its owner gave it.",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "playlist: a list its owner curates and orders (TikTok playlists, YouTube playlists, Facebook playlists and series); collection: posts an account saved from any creator into a named public folder (TikTok collections). New values may be added; treat unknown values as playlist.",
            "enum": [
              "playlist",
              "collection"
            ],
            "type": "string"
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Canonical playlist URL.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "url",
          "type",
          "platform_type",
          "title",
          "description",
          "owner",
          "thumbnail_url",
          "is_collaborative",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "PlaylistMetrics": {
        "properties": {
          "post_count": {
            "description": "Posts in it as the platform counts them (it may count posts that are no longer public, so a walk of its posts can return fewer).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "post_count"
        ],
        "type": "object"
      },
      "PlaylistPlatformSpecific": {
        "properties": {
          "amazon": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AmazonPlaylistSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Amazon influencer's idea list's own fields."
          },
          "applemusic": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApplemusicPlaylistSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Apple Music playlist's or station's own fields."
          },
          "pinterest": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PinterestPlaylistSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Pinterest board's or board section's own fields."
          },
          "spotify": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SpotifyPlaylistSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Spotify playlist's own fields."
          },
          "youtube": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/YouTubePlaylistSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A YouTube playlist's own fields."
          }
        },
        "type": "object"
      },
      "Podcast": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform, date-only or parsed from display text (rating at one decimal, metrics.rating_count from \"2.6K\"). [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "categories": {
            "description": "Categories or topics the platform files it under, as shown (not normalized), the main one first; [] when none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "cover_url": {
            "description": "Cover art URL at the largest size the platform serves; null when it has none. Platform CDN URLs can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "description": "About the show, as plain text; null when it has none or the platform shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native show ID (string), the one in its page's URL.",
            "type": "string"
          },
          "is_explicit": {
            "description": "Marked as holding explicit content by the platform; null when it does not say.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "latest_episode_at": {
            "description": "When its newest episode came out, RFC 3339 UTC; listed in approximate_fields when read from display text or a date alone. Null when the source does not show it.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "media_type": {
            "description": "What its episodes are: audio, video or mixed (both); null when the platform does not say. New values may be added.",
            "enum": [
              "audio",
              "video",
              "mixed",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/PodcastMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "platform": {
            "description": "Platform ID (spotify, youtube, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/PodcastPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "publisher": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The platform account of the publisher; null when the platform names them without an account (always on Spotify)."
          },
          "publisher_name": {
            "description": "Who publishes the show, as the platform names them; null when it does not.",
            "type": [
              "string",
              "null"
            ]
          },
          "rating": {
            "description": "Listeners' average rating, 1 to 5 stars (metrics.rating_count ratings behind it; listed in approximate_fields when the platform rounds it); null when unrated or the platform shows none.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "show_type": {
            "description": "episodic: its episodes stand alone, newest first; serial: they are heard in order, from the first. Null when the platform does not say. New values may be added.",
            "enum": [
              "episodic",
              "serial",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The show's name as the platform lists it.",
            "type": "string"
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Canonical show page URL.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "url",
          "title",
          "description",
          "publisher_name",
          "publisher",
          "cover_url",
          "media_type",
          "show_type",
          "categories",
          "is_explicit",
          "rating",
          "latest_episode_at",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "PodcastMetrics": {
        "properties": {
          "episode_count": {
            "description": "Episodes the platform counts (it may count ones no longer public, so a walk of the episodes can return fewer); null when it does not state one.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "rating_count": {
            "description": "Listeners who rated the show, 0 when none has; null when the platform shows no count.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "episode_count",
          "rating_count"
        ],
        "type": "object"
      },
      "PodcastPlatformSpecific": {
        "type": "object"
      },
      "Post": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform or parsed from display text. A list path (external_links) means the list may be incomplete. [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "author": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "The posting account. An account the platform no longer names (a deleted account) has a null id and username and the platform's label as display_name (Reddit: [deleted]). A post credited to what is no account of the platform's (an Apple Music radio episode's show) has a null id and username, and every other field null too when the platform doesn't name it."
          },
          "coauthors": {
            "description": "Other accounts credited as co-authors of the post (Instagram and Facebook collabs, YouTube collaborations), in the platform's order, author excluded; [] if none.",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "duration_ms": {
            "description": "Length of the primary video or audio in milliseconds; null for other posts.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "hashtags": {
            "description": "Hashtags without #, case kept; [] if none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "id": {
            "description": "Platform-native post ID (string; Instagram shortcode, Reddit with its t3_ prefix).",
            "type": "string"
          },
          "is_nsfw": {
            "description": "Marked adult or sensitive by the platform.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_pinned": {
            "description": "Pinned to the author's profile.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_sponsored": {
            "description": "Labeled as a paid partnership or branded content.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "language": {
            "description": "BCP-47 language of text, when the platform states it.",
            "type": [
              "string",
              "null"
            ]
          },
          "media": {
            "description": "Attachments in display order (carousel items); [] for text posts.",
            "items": {
              "$ref": "#/components/schemas/Media"
            },
            "type": "array"
          },
          "mentions": {
            "description": "Mentioned or tagged usernames without @; [] if none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "metrics": {
            "$ref": "#/components/schemas/PostMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "platform": {
            "description": "Platform ID (tiktok, youtube, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/PostPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "platform_type": {
            "description": "The platform's own product label, lowercase (reel, short, story, live, tweet, …).",
            "type": [
              "string",
              "null"
            ]
          },
          "published_at": {
            "description": "When the post went public, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "text": {
            "description": "Caption, description or body as plain text.",
            "type": [
              "string",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "Cover or poster image URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "Headline (YouTube title, Reddit title); null on caption-only platforms.",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "Normalized content shape. New values may be added; treat unknown values as other.",
            "enum": [
              "video",
              "image",
              "carousel",
              "text",
              "link",
              "audio"
            ],
            "type": "string"
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Canonical post URL.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "url",
          "type",
          "platform_type",
          "title",
          "text",
          "language",
          "published_at",
          "author",
          "coauthors",
          "duration_ms",
          "thumbnail_url",
          "media",
          "hashtags",
          "mentions",
          "is_pinned",
          "is_sponsored",
          "is_nsfw",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "PostMetrics": {
        "properties": {
          "comment_count": {
            "description": "Comments and replies.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "like_count": {
            "description": "Likes, hearts, total reactions or upvotes; never negative. Null when hidden by the owner.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "quote_count": {
            "description": "Quote posts.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "repost_count": {
            "description": "Reposts, retweets or reshares.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "save_count": {
            "description": "Saves, bookmarks or favorites.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "share_count": {
            "description": "Shares or sends (not reposts).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "view_count": {
            "description": "Views or plays.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "view_count",
          "like_count",
          "comment_count",
          "share_count",
          "repost_count",
          "quote_count",
          "save_count"
        ],
        "type": "object"
      },
      "PostPlatformSpecific": {
        "properties": {
          "amazon": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AmazonPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Amazon influencer's storefront photo's or video's own fields."
          },
          "applemusic": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApplemusicPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Apple Music track's, music video's or radio episode's own fields."
          },
          "bluesky": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BlueskyPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Bluesky post's own fields."
          },
          "facebook": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Facebook post's own fields."
          },
          "instagram": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InstagramPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Instagram post's own fields."
          },
          "kick": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KickPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Kick post's own fields."
          },
          "kwai": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KwaiPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Kwai post's own fields."
          },
          "linkedin": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A LinkedIn post's own fields."
          },
          "pinterest": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PinterestPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A pin's own fields."
          },
          "reddit": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RedditPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Reddit post's own fields."
          },
          "rumble": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RumblePostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Rumble video's own fields."
          },
          "snapchat": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SnapchatPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Spotlight's own fields."
          },
          "soundcloud": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SoundcloudPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A SoundCloud track's own fields."
          },
          "spotify": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SpotifyPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Spotify track's or episode's own fields."
          },
          "telegram": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TelegramPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Telegram post's own fields."
          },
          "threads": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ThreadsPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Threads post's own fields."
          },
          "tiktok": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A TikTok post's own fields."
          },
          "truthsocial": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TruthsocialPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Truth Social post's own fields."
          },
          "twitch": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TwitchPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Twitch video's or clip's own fields."
          },
          "x": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/XPostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An X (formerly Twitter) post's own fields."
          },
          "youtube": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/YouTubePostSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A YouTube video's own fields."
          }
        },
        "type": "object"
      },
      "PostSummary": {
        "properties": {
          "author": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "The posting account as the link and the index's text name it (a /@<username>/video/ link's username, the title's display name); its id, avatar_url and is_verified null until the result is filled."
          },
          "id": {
            "description": "Platform-native post ID: the one in the link where the platform's links name it (an X post's /status/<id>), else null until the result is filled.",
            "type": [
              "string",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/PostMetrics",
            "description": "Counts as the index's snippet states them (\"1,234 likes, 56 comments\"; rounded, as old as the index's copy: see approximate_fields), or the platform's current ones once filled; null = not stated."
          },
          "published_at": {
            "description": "When the post went public, as the index's text dates it (often to the day: see approximate_fields); null when it does not.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "text": {
            "description": "Caption or body as the index's snippet quotes it (often cut short: see approximate_fields); null when it quotes none.",
            "type": [
              "string",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "Cover or poster image URL; null until the result is filled (an index's thumbnails are its own copies).",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "Headline, on platforms whose posts have one (a YouTube or Reddit title), as the index's title shows it; null on caption-only platforms (the page's title is the result's title).",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Canonical post URL (equals the result's url).",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "text",
          "published_at",
          "author",
          "thumbnail_url",
          "metrics"
        ],
        "type": "object"
      },
      "Product": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform or parsed from display text (\"10K+ sold\"), and of Facebook's coarse listing coordinates. [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "attributes": {
            "description": "The product's specifications as name/value pairs, in the platform's order; [] when none.",
            "items": {
              "$ref": "#/components/schemas/ProductAttribute"
            },
            "type": "array"
          },
          "availability": {
            "description": "in_stock: can be bought now; out_of_stock: sold out for now (a product can be restocked); pre_order: ships later; pending: a listing with a sale pending; sold: a listing marked sold. Null when the platform does not say. New values may be added; treat unknown values as null.",
            "enum": [
              "in_stock",
              "out_of_stock",
              "pre_order",
              "pending",
              "sold",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "category": {
            "description": "The platform's most specific category label (Bicycles, Vitamins & Supplements), as shown; not normalized across platforms.",
            "type": [
              "string",
              "null"
            ]
          },
          "category_id": {
            "description": "The platform's ID of that category (what its category browsing and filters take).",
            "type": [
              "string",
              "null"
            ]
          },
          "condition": {
            "description": "Item condition, coarse: new, used (any grade) or refurbished; null when the platform does not say. The platform's own grade is condition_label. New values may be added; treat unknown values as used.",
            "enum": [
              "new",
              "used",
              "refurbished",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "condition_label": {
            "description": "The condition as the platform labels it (Used - Like New, Used - Good, Pre-owned).",
            "type": [
              "string",
              "null"
            ]
          },
          "country_code": {
            "description": "ISO 3166-1 alpha-2 market the product is offered in; prices, stock and shipping are that market's.",
            "type": [
              "string",
              "null"
            ]
          },
          "currency": {
            "description": "ISO 4217 code of every amount of this product (USD); null when no amount is shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "description": "Description as plain text (paragraphs separated by blank lines); null when it has none or the source does not show it (lists and search results).",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native product or listing ID (string).",
            "type": "string"
          },
          "max_price": {
            "description": "Highest current variant price, in major units of currency; equal to price when every variant costs the same; null when unknown (a source that shows one price).",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "media": {
            "description": "Product images in the platform's order (main image first), then any product video; [] when none.",
            "items": {
              "$ref": "#/components/schemas/Media"
            },
            "type": "array"
          },
          "original_price": {
            "description": "Price before the discount (the struck-through list price), in major units of currency; null when the platform shows no earlier price (not discounted, or not shown).",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "platform": {
            "description": "Platform ID (tiktokshop, facebook, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/ProductPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>): TikTok Shop's brand, rating, variants, stock and units sold; Marketplace's location and listing date. Each null when unknown."
          },
          "price": {
            "description": "Current price in major units of currency (58.47), discounts applied; for a product whose variants cost different amounts, the lowest (the platform's \"from\" price). Coupons and shipping excluded. 0 = free; null when not shown.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "seller": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The shop or account selling it; null only when the source does not show it."
          },
          "shipping": {
            "$ref": "#/components/schemas/ProductShipping",
            "description": "Delivery terms as shown to a buyer in the product's market; each null when not shown."
          },
          "thumbnail_url": {
            "description": "Main product image URL. Platform CDN URLs can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "Product name or listing title, as the seller wrote it.",
            "type": "string"
          },
          "type": {
            "description": "product: a catalog product a shop sells in many units, often in variants (TikTok Shop, Instagram and YouTube shopping); listing: a single item a person or business lists for sale (Facebook Marketplace). New values may be added; treat unknown values as product.",
            "enum": [
              "product",
              "listing"
            ],
            "type": "string"
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a list or search result that does not show attributes or variants); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Canonical product page URL.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "url",
          "type",
          "title",
          "description",
          "category",
          "category_id",
          "seller",
          "price",
          "max_price",
          "original_price",
          "currency",
          "availability",
          "condition",
          "condition_label",
          "thumbnail_url",
          "media",
          "attributes",
          "shipping",
          "country_code",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "ProductAttribute": {
        "properties": {
          "name": {
            "description": "Specification name, as shown (Brand, Material, Condition).",
            "type": "string"
          },
          "value": {
            "description": "Its value, as shown.",
            "type": "string"
          }
        },
        "required": [
          "name",
          "value"
        ],
        "type": "object"
      },
      "ProductPlatformSpecific": {
        "properties": {
          "amazon": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AmazonProductSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Amazon product's own fields."
          },
          "facebook": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookProductSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Facebook Marketplace listing's own fields."
          },
          "tiktokshop": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokShopProductSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A TikTok Shop product's own fields."
          }
        },
        "type": "object"
      },
      "ProductShipping": {
        "properties": {
          "fee": {
            "description": "Standard shipping fee in major units of the product's currency; 0 = free shipping.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "is_offered": {
            "description": "The seller ships it (false: local pickup only).",
            "type": [
              "boolean",
              "null"
            ]
          }
        },
        "required": [
          "is_offered",
          "fee"
        ],
        "type": "object"
      },
      "ProductVariant": {
        "properties": {
          "availability": {
            "description": "Whether this variant can be bought now; null when not shown. New values may be added; treat unknown values as null.",
            "enum": [
              "in_stock",
              "out_of_stock",
              "pre_order",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native variant (SKU) ID; review.variant_id names it.",
            "type": "string"
          },
          "image_url": {
            "description": "Image of this variant (its color swatch or photo). Platform CDN URLs can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "options": {
            "description": "The option values that make this variant (Color: Black); [] for a product's only variant.",
            "items": {
              "$ref": "#/components/schemas/ProductVariantOption"
            },
            "type": "array"
          },
          "original_price": {
            "description": "This variant's price before the discount; null when no earlier price is shown.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "price": {
            "description": "Current price of this variant, in major units of the product's currency.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "stock_count": {
            "description": "Units in stock as the platform reports them (platforms may cap the number they show); null when hidden.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "title": {
            "description": "Variant name as shown, else its options joined (Color: Black, Size: M).",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "options",
          "price",
          "original_price",
          "availability",
          "stock_count",
          "image_url"
        ],
        "type": "object"
      },
      "ProductVariantOption": {
        "properties": {
          "name": {
            "description": "Option name, as shown (Color, Size).",
            "type": "string"
          },
          "value": {
            "description": "The variant's value of it (Black, M).",
            "type": "string"
          }
        },
        "required": [
          "name",
          "value"
        ],
        "type": "object"
      },
      "Profile": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform or parsed from display text (e.g. metrics.follower_count). A list path (external_links) means the list may be incomplete. [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "avatar_url": {
            "description": "Profile picture URL (largest available). Platform CDN URLs can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "banner_url": {
            "description": "Header or cover image URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "bio": {
            "description": "Profile bio, channel description or page about text; null when empty or not exposed.",
            "type": [
              "string",
              "null"
            ]
          },
          "category": {
            "description": "Platform category label (e.g. Musician, Media & Entertainment), as shown; not normalized. Often set only for business or creator accounts.",
            "type": [
              "string",
              "null"
            ]
          },
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country the platform states for the account.",
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "description": "Account creation or join date, RFC 3339 UTC (some platforms give only the day: see approximate_fields).",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "display_name": {
            "description": "Display name, channel title or page name; null when empty or not exposed.",
            "type": [
              "string",
              "null"
            ]
          },
          "external_links": {
            "description": "Links in the bio or channel links; [] if none or not exposed.",
            "items": {
              "$ref": "#/components/schemas/Link"
            },
            "type": "array"
          },
          "id": {
            "description": "Platform-native account ID (string; YouTube UC…, Reddit t2_…).",
            "type": "string"
          },
          "is_private": {
            "description": "True when the account's posts are not public.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_verified": {
            "description": "Platform verification badge; null where the platform has no badge.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "location": {
            "description": "Self-declared location text.",
            "type": [
              "string",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/ProfileMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "platform": {
            "description": "Platform ID (tiktok, youtube, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/ProfilePlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "type": {
            "description": "Coarse account kind, as the platform labels it; unknown when it does not (TikTok labels organizations only). New values may be added; treat unknown values as unknown.",
            "enum": [
              "person",
              "organization",
              "community",
              "unknown"
            ],
            "type": "string"
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Canonical profile URL.",
            "format": "uri",
            "type": "string"
          },
          "username": {
            "description": "Handle without the @; null when the account has none.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "platform",
          "id",
          "username",
          "display_name",
          "url",
          "type",
          "bio",
          "avatar_url",
          "banner_url",
          "is_verified",
          "is_private",
          "category",
          "external_links",
          "location",
          "country_code",
          "created_at",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "ProfileMetrics": {
        "properties": {
          "follower_count": {
            "description": "Followers or subscribers.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "following_count": {
            "description": "Accounts this profile follows.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "post_count": {
            "description": "Posts or videos as the platform counts them on the profile (for a private account, posts the caller cannot see).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "total_like_count": {
            "description": "Likes received across all of the profile's posts (not likes given).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "total_view_count": {
            "description": "Lifetime views across all of the profile's posts.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "follower_count",
          "following_count",
          "post_count",
          "total_like_count",
          "total_view_count"
        ],
        "type": "object"
      },
      "ProfilePlatformSpecific": {
        "properties": {
          "amazon": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AmazonProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Amazon seller's or storefront's own fields."
          },
          "applemusic": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApplemusicProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Apple Music artist's own fields."
          },
          "bluesky": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BlueskyProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Bluesky account's own fields."
          },
          "facebook": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Facebook Page's or person's own fields."
          },
          "google": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/GoogleProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Google advertiser's own fields."
          },
          "instagram": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InstagramProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Instagram account's own fields."
          },
          "komi": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KomiProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Komi page's own fields."
          },
          "kwai": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KwaiProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Kwai account's own fields."
          },
          "linkbio": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkbioProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Lnk.Bio page's own fields."
          },
          "linkedin": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A LinkedIn Page's or member's own fields."
          },
          "linkme": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkmeProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Linkme page's own fields."
          },
          "linktree": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinktreeProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Linktree page's own fields."
          },
          "pillar": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PillarProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Pillar page's own fields."
          },
          "pinterest": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PinterestProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Pinterest account's own fields."
          },
          "reddit": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RedditProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Reddit account's own fields."
          },
          "rumble": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RumbleProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Rumble channel's or user's own fields."
          },
          "snapchat": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SnapchatProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Snapchat account's own fields."
          },
          "soundcloud": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SoundcloudProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A SoundCloud account's own fields."
          },
          "spotify": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SpotifyProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Spotify artist's own fields."
          },
          "telegram": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TelegramProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Telegram channel's, group's, user's or bot's own fields."
          },
          "threads": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ThreadsProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Threads account's own fields."
          },
          "tiktok": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A TikTok account's own fields."
          },
          "truthsocial": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TruthsocialProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Truth Social account's own fields."
          },
          "twitch": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TwitchProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Twitch channel's own fields."
          },
          "x": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/XProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An X (formerly Twitter) account's own fields."
          },
          "youtube": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/YouTubeProfileSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A YouTube channel's own fields."
          }
        },
        "type": "object"
      },
      "ProfileRef": {
        "properties": {
          "avatar_url": {
            "description": "Profile picture URL. Platform CDN URLs can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "display_name": {
            "description": "Display name shown on the profile.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native account ID; null when only the handle is known.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_verified": {
            "description": "Platform verification badge; null where the platform has no badge.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "url": {
            "description": "Canonical profile URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "username": {
            "description": "Handle without the @; null when the account has none.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "username",
          "display_name",
          "url",
          "avatar_url",
          "is_verified"
        ],
        "type": "object"
      },
      "ProfileSummary": {
        "properties": {
          "avatar_url": {
            "description": "Profile picture URL; null until the result is filled (an index's thumbnails are its own copies). Platform CDN URLs can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "bio": {
            "description": "Profile bio as the index's snippet quotes it (often cut short: see approximate_fields); null when it quotes none.",
            "type": [
              "string",
              "null"
            ]
          },
          "display_name": {
            "description": "Display name, as the index's title shows it; null when it shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native account ID; null until the result is filled (the index shows only the handle).",
            "type": [
              "string",
              "null"
            ]
          },
          "is_verified": {
            "description": "Platform verification badge; null until the result is filled, or where the platform has no badge.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/ProfileMetrics",
            "description": "Counts as the index's snippet states them (rounded, as old as the index's copy: see approximate_fields), or the platform's current ones once filled; null = not stated."
          },
          "url": {
            "description": "Canonical profile URL (equals the result's url).",
            "format": "uri",
            "type": "string"
          },
          "username": {
            "description": "Handle without the @, as the matched link names it; null when the link names the account only by its number.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "username",
          "display_name",
          "url",
          "bio",
          "avatar_url",
          "is_verified",
          "metrics"
        ],
        "type": "object"
      },
      "Range": {
        "properties": {
          "lower_bound": {
            "description": "Inclusive lower bound.",
            "format": "int64",
            "type": "integer"
          },
          "upper_bound": {
            "description": "Inclusive upper bound; null when open-ended (e.g. \">1M\"). Equal to lower_bound when exact.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "lower_bound",
          "upper_bound"
        ],
        "type": "object"
      },
      "RatingDistribution": {
        "properties": {
          "five_star_count": {
            "description": "Reviews rating 5 stars.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "four_star_count": {
            "description": "Reviews rating 4 stars.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "one_star_count": {
            "description": "Reviews rating 1 star.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "three_star_count": {
            "description": "Reviews rating 3 stars.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "two_star_count": {
            "description": "Reviews rating 2 stars.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "one_star_count",
          "two_star_count",
          "three_star_count",
          "four_star_count",
          "five_star_count"
        ],
        "type": "object"
      },
      "RedditCommentPost": {
        "properties": {
          "comment_count": {
            "description": "Comments on the post.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_nsfw": {
            "description": "The post is marked NSFW (18+).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_spoiler": {
            "description": "The post is marked as a spoiler.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "published_at": {
            "description": "When the post was submitted, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "score": {
            "description": "The post's net score as Reddit shows it (floored at 0 on display).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "title": {
            "description": "The post's title.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The post's permalink.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "title",
          "url",
          "score",
          "comment_count",
          "published_at",
          "is_nsfw",
          "is_spoiler"
        ],
        "type": "object"
      },
      "RedditCommentSpecific": {
        "properties": {
          "award_count": {
            "description": "Awards the comment received.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "depth": {
            "description": "How deep in the post's thread the comment is: 0 for a comment on the post, 1 for a reply to one, and so on.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "distinguished": {
            "description": "The role the author spoke in, when they marked the comment with it: moderator or admin; null for an ordinary comment.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_collapsed": {
            "description": "Reddit shows the comment collapsed (a low score, a moderator's or crowd-control setting, or a subreddit's rule).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_deleted": {
            "description": "The comment's body was deleted by its author or removed by a moderator or Reddit; text is then empty. Reddit keeps such a comment in the thread when it has replies.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "more_replies_count": {
            "description": "Replies under this comment (with their own replies) that the page leaves out, as Reddit counts them in its \"N more replies\" link: request the comment's url to page through them. 0 when every reply Reddit has is included.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "post": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RedditCommentPost"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post the comment is on, as Reddit shows it beside the comment (search results); null where the endpoint does not show it."
          },
          "reply_to_author": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The author of the comment this one replies to, where the list names them (a user's comments: Reddit's \"replied to u/…\"); null where Reddit does not name them (a comment on the post, a deleted parent account) and where parent_id places the comment in its thread."
          },
          "score": {
            "description": "Net score as Reddit shows it: upvotes minus downvotes, fuzzed by Reddit; negative for a comment most votes are against. Null when Reddit hides it (a subreddit that hides recent comments' scores, a deleted comment).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "subreddit": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RedditSubredditRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The subreddit of the post the comment is on; for a post on a user's profile, the profile's own subreddit (u_<username>)."
          }
        },
        "required": [
          "subreddit",
          "score",
          "depth",
          "award_count",
          "distinguished",
          "is_collapsed",
          "is_deleted",
          "more_replies_count",
          "reply_to_author",
          "post"
        ],
        "type": "object"
      },
      "RedditCommentsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 200), Reddit's Controversial order of comments (most evenly divided votes first), each followed by the replies Reddit shows with sort=controversial, Reddit's New order of comments (newest first), each followed by the replies Reddit shows with sort=newest, Reddit's Old order of comments (oldest first), each followed by the replies Reddit shows with sort=oldest, Reddit's Top order of comments (highest score first), each followed by the replies Reddit shows with sort=popular, Reddit's Q&A order (the comments the post's author answered first), each followed by the replies Reddit shows with sort=qa, Reddit's own order for the post (Best, or the order its moderators suggest), each comment followed by the replies Reddit shows with sort=relevance. In Reddit's words: `metrics.like_count` is upvotes (score).",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "RedditCommunitySpecific": {
        "properties": {
          "is_quarantined": {
            "description": "True when Reddit has quarantined it (shown only after a warning).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "member_nickname": {
            "description": "What the subreddit calls its members (gophers on r/golang); null when it has no nickname.",
            "type": [
              "string",
              "null"
            ]
          },
          "weekly_contribution_count": {
            "description": "Posts and comments in the last week, as the subreddit's page shows them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "weekly_visitor_count": {
            "description": "Unique visitors in the last week, as the subreddit's page shows them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "weekly_visitor_count",
          "weekly_contribution_count",
          "member_nickname",
          "is_quarantined"
        ],
        "type": "object"
      },
      "RedditEngagementResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Engagement",
            "description": "In Reddit's words: `metrics.comment_to_like_ratio` is comment-to-upvote ratio, `metrics.likes_per_post` is upvotes (score) per post, `posts[].post.metrics.like_count` is upvotes (score)."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "RedditPostResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post",
            "description": "In Reddit's words: `metrics.like_count` is upvotes (score)."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "RedditPostSpecific": {
        "properties": {
          "award_count": {
            "description": "Awards the post received.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "crosspost_of": {
            "description": "The post this one is a crosspost of; null when it is not a crosspost.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "domain": {
            "description": "The linked site's domain (youtu.be, i.redd.it, v.redd.it), or self.<subreddit> for a text post.",
            "type": [
              "string",
              "null"
            ]
          },
          "flair": {
            "description": "The post's flair text; null when it has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_archived": {
            "description": "Archived: too old for new votes or comments.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_locked": {
            "description": "Locked by the moderators: no new comments.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_spoiler": {
            "description": "Marked as a spoiler.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "link_url": {
            "description": "The page a link post points to; null for other posts.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "score": {
            "description": "Net score as Reddit shows it: upvotes minus downvotes, fuzzed by Reddit. Reddit floors a post's shown score at 0, so this is null when it shows 0 for a post most votes are against (upvote_ratio below 0.5): its true score is negative and unknown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "subreddit": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RedditSubredditRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The subreddit the post was submitted to; for a post on a user's profile, the profile's own subreddit (u_<username>)."
          },
          "upvote_ratio": {
            "description": "Share of votes that are upvotes, from 0 to 1.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "subreddit",
          "score",
          "upvote_ratio",
          "award_count",
          "flair",
          "domain",
          "link_url",
          "is_spoiler",
          "is_locked",
          "is_archived",
          "crosspost_of"
        ],
        "type": "object"
      },
      "RedditPostsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 25), Reddit's Controversial order (most evenly divided votes first), of all time or of the time filter that covers since with sort=controversial, newest first with sort=newest, Reddit's Top order (highest score first), of all time or of the time filter that covers since with sort=popular, Reddit's Hot order (recent posts ranked by their votes) with sort=relevance. In Reddit's words: `metrics.like_count` is upvotes (score).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "RedditProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "RedditProfileSpecific": {
        "properties": {
          "comment_karma": {
            "description": "Karma from the account's comments.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "contribution_count": {
            "description": "Posts and comments the account has made, as its profile counts them (Reddit updates the count daily).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_admin": {
            "description": "True for a Reddit employee's account (the Reddit Admin badge).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_nsfw": {
            "description": "True when the profile is marked NSFW (18+): Reddit shows its posts to logged-out visitors only behind an age prompt.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_premium": {
            "description": "True when the account has Reddit Premium (the badge beside its name).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "karma": {
            "description": "Total karma, as the profile shows it: post karma plus comment karma. Reddit's own score of the upvotes the account's posts and comments received, fuzzed and not a count of votes.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "moderated_subreddits": {
            "description": "Subreddits the account moderates, as its profile lists them; Reddit lists the first few only (the list is then in approximate_fields). [] when it moderates none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/RedditSubredditRef"
            },
            "type": "array"
          },
          "post_karma": {
            "description": "Karma from the account's posts.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "trophies": {
            "description": "The account's Trophy Case, in Reddit's order; [] when it has none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/RedditTrophy"
            },
            "type": "array"
          }
        },
        "required": [
          "karma",
          "post_karma",
          "comment_karma",
          "contribution_count",
          "is_admin",
          "is_premium",
          "is_nsfw",
          "moderated_subreddits",
          "trophies"
        ],
        "type": "object"
      },
      "RedditProfile_commentsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 25), Reddit's Controversial order (most evenly divided votes first), of all time or of the time filter that covers since with sort=controversial, newest first with sort=newest, Reddit's Top order (highest score first), of all time or of the time filter that covers since with sort=popular, Reddit's Hot order (recent comments ranked by their votes) with sort=relevance. In Reddit's words: `metrics.like_count` is upvotes (score).",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "RedditSearch_commentsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 10), newest first with sort=newest, Reddit's Top: highest score first with sort=popular, Reddit's search ranking (best match) with sort=relevance. In Reddit's words: `metrics.like_count` is upvotes (score).",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "RedditSearch_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 7), Reddit's Comments order (most comments first) with sort=most_comments, newest first with sort=newest, Reddit's Top order (highest score first) with sort=popular, Reddit's relevance order (its search ranking) with sort=relevance. In Reddit's words: `metrics.like_count` is upvotes (score).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "RedditSearch_profilesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 7), Reddit's relevance order.",
            "items": {
              "$ref": "#/components/schemas/Profile"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "RedditSearch_subredditsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 10), Reddit's relevance order. In Reddit's words: `metrics.member_count` is subscribers.",
            "items": {
              "$ref": "#/components/schemas/Community"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "RedditSubredditRef": {
        "properties": {
          "id": {
            "description": "Reddit's subreddit ID (t5_…).",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "The subreddit's name without r/.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The subreddit's URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "url"
        ],
        "type": "object"
      },
      "RedditSubredditResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Community",
            "description": "In Reddit's words: `metrics.member_count` is subscribers."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "RedditSubreddit_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 25), Reddit's Best order (its default ranking of a subreddit's posts) with sort=best, Reddit's Controversial order (most evenly divided votes first, within the time filter since picks) with sort=controversial, Reddit's Hot order (recent posts gaining votes fast first) with sort=hot, newest first with sort=newest, Reddit's Top order (highest score first, within the time filter since picks) with sort=popular, Reddit's Rising order (new posts gaining votes fastest first) with sort=rising. In Reddit's words: `metrics.like_count` is upvotes (score).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "RedditTranscriptResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Transcript"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "RedditTranscriptSpecific": {
        "properties": {
          "caption_url": {
            "description": "The WebVTT file of Reddit's caption track used (public, unsigned); null for speech-to-text.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "video_id": {
            "description": "The video's ID on Reddit's video host (v.redd.it/<video_id>); null when unknown.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "video_id",
          "caption_url"
        ],
        "type": "object"
      },
      "RedditTrophy": {
        "properties": {
          "description": {
            "description": "What it was awarded for, as Reddit describes it; null when it shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "granted_at": {
            "description": "The day it was awarded, RFC 3339 UTC at midnight (Reddit shows the day only), for the trophies Reddit dates; null otherwise.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "image_url": {
            "description": "The trophy's image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "The trophy's name (Verified Email, 10-Year Club, Best Comment).",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "What it links to (the awarded comment or post, an event page); null when it links nowhere.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "description",
          "granted_at",
          "image_url",
          "url"
        ],
        "type": "object"
      },
      "ResponseMeta": {
        "properties": {
          "client_request_id": {
            "description": "Your x-client-request-id, echoed; null when you sent none.",
            "type": [
              "string",
              "null"
            ]
          },
          "credits_charged": {
            "description": "Credits charged for this request (0 for errors and cache hits).",
            "format": "int64",
            "type": "integer"
          },
          "credits_remaining": {
            "description": "Account balance after this request (the x-credits-remaining header); for a busy account an estimate that may not yet subtract concurrent requests (about a second of usage), never below the real balance; null when SocialTap could not read it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "fetched_at": {
            "description": "When the data was fetched from the platform, RFC 3339 UTC (older than the request for cache hits).",
            "format": "date-time",
            "type": "string"
          },
          "input": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InputRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "What the request's url or handle resolved to: kind, platform ID and canonical URL, so you can confirm what was fetched; null for searches."
          },
          "is_cached": {
            "description": "True when served from the cache (free); see max_age.",
            "type": "boolean"
          },
          "latency_ms": {
            "description": "Time SocialTap spent on the request, in milliseconds.",
            "format": "int64",
            "type": "integer"
          },
          "platform": {
            "description": "Platform ID of the endpoint (youtube, tiktok, …).",
            "examples": [
              "youtube"
            ],
            "type": "string"
          },
          "request_id": {
            "description": "Unique request ID; include it when contacting support.",
            "type": "string"
          },
          "source": {
            "description": "Which upstream strategy produced the data.",
            "examples": [
              "captions"
            ],
            "type": "string"
          },
          "warnings": {
            "description": "Things to act on that did not fail the request: a deprecated endpoint, partial data, items a list's walk leaves out. [] when none.",
            "items": {
              "$ref": "#/components/schemas/Warning"
            },
            "type": "array"
          }
        },
        "required": [
          "request_id",
          "platform",
          "source",
          "is_cached",
          "credits_charged",
          "latency_ms",
          "fetched_at",
          "input",
          "credits_remaining",
          "client_request_id",
          "warnings"
        ],
        "type": "object"
      },
      "Review": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform or parsed from display text (a date-only time). [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "author": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "The reviewing account, as the platform shows it (some platforms mask the name, e.g. G**a, and show no handle); every field null for an anonymous review."
          },
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country the review was written in, as the platform states it.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native review ID (string).",
            "type": "string"
          },
          "is_incentivized": {
            "description": "The platform marks the review as written in exchange for a free product or reward.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_verified_purchase": {
            "description": "The platform marks the reviewer as having bought the product through it.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "language": {
            "description": "BCP-47 language of text, when the platform states it.",
            "type": [
              "string",
              "null"
            ]
          },
          "media": {
            "description": "Photos and videos attached to the review; [] when none.",
            "items": {
              "$ref": "#/components/schemas/Media"
            },
            "type": "array"
          },
          "metrics": {
            "$ref": "#/components/schemas/ReviewMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "platform": {
            "description": "Platform ID (tiktokshop, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/ReviewPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "product_id": {
            "description": "ID of the product reviewed (equals product.id); null only for a review of something other than a product.",
            "type": [
              "string",
              "null"
            ]
          },
          "published_at": {
            "description": "When the review was posted, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "rating": {
            "description": "Star rating, 1 to 5; null when the review gives none.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "text": {
            "description": "Review body as plain text; null for a rating without text.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The review's headline; null when it has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see a review's photos); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Permalink, when the platform has one (TikTok Shop reviews have none).",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "variant_id": {
            "description": "ID of the variant bought: one of the product's variants (TikTok Shop: product.platform_specific.tiktokshop.variants[].id).",
            "type": [
              "string",
              "null"
            ]
          },
          "variant_title": {
            "description": "The variant bought, as the platform labels it (Color: Black).",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "platform",
          "id",
          "product_id",
          "url",
          "rating",
          "title",
          "text",
          "language",
          "author",
          "variant_id",
          "variant_title",
          "media",
          "country_code",
          "is_verified_purchase",
          "is_incentivized",
          "published_at",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "ReviewMetrics": {
        "properties": {
          "helpful_count": {
            "description": "Readers who marked the review helpful; null when the platform shows no such count.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "helpful_count"
        ],
        "type": "object"
      },
      "ReviewPlatformSpecific": {
        "type": "object"
      },
      "RumbleCaptionTrack": {
        "properties": {
          "is_auto_generated": {
            "description": "Generated by Rumble's speech recognition.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "label": {
            "description": "Rumble's label (\"English (auto)\").",
            "type": [
              "string",
              "null"
            ]
          },
          "language": {
            "description": "Language code (en, es, …).",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "WebVTT file URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "language",
          "label",
          "url",
          "is_auto_generated"
        ],
        "type": "object"
      },
      "RumbleCommentSpecific": {
        "properties": {
          "author_badges": {
            "description": "The badges Rumble shows beside the commenter's name, by their label as Rumble writes it (seen: Verified, Admin, Moderator, Supporter, Supporter+, Supporter++, Sub, Locals Supporter; new labels may appear). [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "dislike_count": {
            "description": "Thumbs-down votes on the comment. Exact below 1,000; from 1,000 Rumble shows a label such as \"1.31K\", taken to be cut to three significant digits as Rumble's other counts are (not checked against an exact count), and listed in approximate_fields.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "dislike_count",
          "author_badges"
        ],
        "type": "object"
      },
      "RumbleCommentsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 500), newest first with sort=newest, Rumble's Sort by likes order of comments, each followed by its replies with sort=popular.",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "RumbleEngagementResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Engagement"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "RumbleFile": {
        "properties": {
          "bitrate_kbps": {
            "description": "Bitrate in kbit/s.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "format": {
            "description": "mp4 or webm file, hls playlist (all qualities), tar (one HLS quality packed in one file; url is its playlist) or aac audio. New values may be added.",
            "enum": [
              "mp4",
              "webm",
              "hls",
              "tar",
              "aac",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "height": {
            "description": "Height in pixels; null for audio and playlists.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "kind": {
            "description": "video (picture and sound), audio (sound only) or preview (the seek bar's low-resolution video, no sound). New values may be added.",
            "enum": [
              "video",
              "audio",
              "preview",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "size_bytes": {
            "description": "File size in bytes; null when Rumble does not state it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "url": {
            "description": "File or playlist URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "width": {
            "description": "Width in pixels; null for audio and playlists.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "kind",
          "format",
          "url",
          "width",
          "height",
          "bitrate_kbps",
          "size_bytes"
        ],
        "type": "object"
      },
      "RumblePostResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "RumblePostSpecific": {
        "properties": {
          "author_follower_count": {
            "description": "The channel's or user's follower count. Exact in Rumble's JSON (shorts, lists); a video's page cuts it to three significant digits (in approximate_fields).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "caption_tracks": {
            "description": "Caption tracks (WebVTT); [] when none.",
            "items": {
              "$ref": "#/components/schemas/RumbleCaptionTrack"
            },
            "type": "array"
          },
          "category": {
            "description": "Rumble's primary category (News, Podcasts, …).",
            "type": [
              "string",
              "null"
            ]
          },
          "concurrent_viewer_count": {
            "description": "Viewers watching a live stream now; null when not live.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "dislike_count": {
            "description": "Thumbs-down votes. Exact in Rumble's JSON (shorts, grid lists); a video's page and the older HTML cards cut it to three significant digits from 1,000 (in approximate_fields).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "embed_id": {
            "description": "The video's embed player ID (rumble.com/embed/<embed_id>/): its own namespace, not id.",
            "type": [
              "string",
              "null"
            ]
          },
          "embed_url": {
            "description": "The embeddable player URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "files": {
            "description": "Every file and stream Rumble's player offers, largest video first; [] when none.",
            "items": {
              "$ref": "#/components/schemas/RumbleFile"
            },
            "type": "array"
          },
          "is_age_restricted": {
            "description": "Viewers must confirm their age to watch; null when the source does not show it.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_live_now": {
            "description": "A live stream on air now.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "keywords": {
            "description": "The uploader's tags; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "live_started_at": {
            "description": "When a live stream went on air; null if never live.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "numeric_id": {
            "description": "Rumble's numeric video ID, which its own services use.",
            "type": [
              "string",
              "null"
            ]
          },
          "scheduled_start_at": {
            "description": "When a scheduled live stream is due to start; null otherwise.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "secondary_category": {
            "description": "Rumble's secondary category; null when none.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "embed_id",
          "embed_url",
          "numeric_id",
          "dislike_count",
          "category",
          "secondary_category",
          "keywords",
          "caption_tracks",
          "files",
          "is_live_now",
          "live_started_at",
          "scheduled_start_at",
          "concurrent_viewer_count",
          "is_age_restricted",
          "author_follower_count"
        ],
        "type": "object"
      },
      "RumblePostsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 25), Rumble's upload order (newest uploads first, not strictly by published_at) with sort=newest, Rumble's View count order (most viewed first) with sort=popular.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "RumbleProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "RumbleProfileSpecific": {
        "properties": {
          "account_type": {
            "description": "channel for a Rumble channel (rumble.com/c/<name>), user for a Rumble user (rumble.com/user/<name>: the account that uploads, which can own channels). Null when unknown. New values may be added; treat unknown values as unknown.",
            "enum": [
              "channel",
              "user",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "numeric_id": {
            "description": "Rumble's numeric ID of the channel or the user, in decimal (the channel's is the number in its rumble.com/c/c-<id> link). Channels and users are numbered separately, so the same number can name a channel and a user: id is the unambiguous reference. Null when unknown.",
            "type": [
              "string",
              "null"
            ]
          },
          "user_id": {
            "description": "The id of the Rumble user that owns the channel (_u…, the id this endpoint answers for that user); for a user, its own id. Channels of one owner share it. Null when the page does not show it.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "account_type",
          "numeric_id",
          "user_id"
        ],
        "type": "object"
      },
      "RumbleSearch_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 36), newest first with sort=newest, Rumble's View count order (most viewed first) with sort=popular, Rumble's relevance order with sort=relevance.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "RumbleTranscriptResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Transcript"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "RumbleTranscriptSpecific": {
        "properties": {
          "caption_tracks": {
            "description": "Every caption track Rumble offers for the video (WebVTT); [] when none.",
            "items": {
              "$ref": "#/components/schemas/RumbleCaptionTrack"
            },
            "type": "array"
          },
          "caption_url": {
            "description": "The WebVTT file of the caption track used; null for speech-to-text.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "track_label": {
            "description": "Rumble's label of the caption track used (\"English (auto)\"); null for speech-to-text.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "track_label",
          "caption_url",
          "caption_tracks"
        ],
        "type": "object"
      },
      "ScheduledEvent": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform or parsed from display text (\"7.3K interested\": platform_specific.facebook.metrics.interested_count). [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "categories": {
            "description": "Categories the platform files it under, as shown (not normalized), the main one first; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "community_id": {
            "description": "ID of the community it belongs to (the Facebook group it was created in; community.id); null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "cover_url": {
            "description": "The event's cover image (a video cover's poster frame); null when it has none. Platform CDN URLs can expire within days.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "description": "Its description as plain text; null when it has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "end_at": {
            "description": "When it ends, RFC 3339 UTC; null when its hosts set no end or the platform does not show it.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "hosts": {
            "description": "The accounts hosting it (pages and people), the main organizer first; [] when none are shown (listed in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "id": {
            "description": "Platform-native event ID (string; Facebook's numeric event ID).",
            "type": "string"
          },
          "is_online": {
            "description": "Held online (a stream or video call) rather than at a venue.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/EventMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "name": {
            "description": "The event's name as its page shows it.",
            "type": "string"
          },
          "parent_id": {
            "description": "ID of the event series this date belongs to (a recurring event's parent event); null for a single event or the series itself.",
            "type": [
              "string",
              "null"
            ]
          },
          "place": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PlaceRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "Where it is held; null for an online event with no venue or when not shown."
          },
          "platform": {
            "description": "Platform ID (facebook, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/EventPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "start_at": {
            "description": "When it starts, RFC 3339 UTC; null only when the platform shows no start.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "description": "At fetch time: scheduled (not started), ongoing (started, not over), ended (over), canceled (called off by its hosts); unknown when the source that answered does not show it (a fallback whose results hold only a name and a picture). New values may be added; treat any other value as unknown.",
            "enum": [
              "scheduled",
              "ongoing",
              "ended",
              "canceled",
              "unknown"
            ],
            "type": "string"
          },
          "ticket_url": {
            "description": "Where to buy tickets or register, as the platform links it; null when none is linked.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "time_zone": {
            "description": "The event's IANA time zone (America/New_York) when the platform states one; null otherwise (utc_offset_minutes still gives its local time).",
            "type": [
              "string",
              "null"
            ]
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Canonical event page URL (https://www.facebook.com/events/<id>/).",
            "format": "uri",
            "type": "string"
          },
          "utc_offset_minutes": {
            "description": "The event's offset from UTC at its start, in minutes (-240 for 5:00 PM EDT): its local start time is start_at plus this offset; null when unknown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "platform",
          "id",
          "url",
          "name",
          "description",
          "status",
          "start_at",
          "end_at",
          "time_zone",
          "utc_offset_minutes",
          "is_online",
          "place",
          "hosts",
          "cover_url",
          "categories",
          "ticket_url",
          "parent_id",
          "community_id",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "Segment": {
        "properties": {
          "end_ms": {
            "description": "End time in milliseconds from the beginning of the media.",
            "format": "int64",
            "type": "integer"
          },
          "start_ms": {
            "description": "Start time in milliseconds from the beginning of the media.",
            "format": "int64",
            "type": "integer"
          },
          "text": {
            "description": "Cue text, whitespace-normalized.",
            "type": "string"
          }
        },
        "required": [
          "start_ms",
          "end_ms",
          "text"
        ],
        "type": "object"
      },
      "SnapchatCommentSpecific": {
        "properties": {
          "author_user_id": {
            "description": "The commenter's user ID, the same as platform_specific.snapchat.user_id of their snapchat.profile. It stays when they replace their public profile, which changes author.id; null when Snapchat names no account for the comment.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "author_user_id"
        ],
        "type": "object"
      },
      "SnapchatCommentsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 26), Snapchat's own ranking of the Spotlight's comments; a comment's replies oldest first.",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "SnapchatHighlight": {
        "properties": {
          "id": {
            "description": "The saved Story's ID.",
            "type": "string"
          },
          "snaps": {
            "description": "Its Snaps, in the order it plays them.",
            "items": {
              "$ref": "#/components/schemas/SnapchatSnap"
            },
            "type": "array"
          },
          "thumbnail_url": {
            "description": "Its cover image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The title the account gave it; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The saved Story's link.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "id",
          "title",
          "thumbnail_url",
          "url",
          "snaps"
        ],
        "type": "object"
      },
      "SnapchatLensCredit": {
        "properties": {
          "id": {
            "description": "The Lens's ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "The Lens's name.",
            "type": [
              "string",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "The Lens's icon.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The Lens's page.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "url",
          "thumbnail_url"
        ],
        "type": "object"
      },
      "SnapchatPlaceCredit": {
        "properties": {
          "category": {
            "description": "Its category as Snapchat words it (Bars, Amusement Park).",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "The place's ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "The place's name.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The place's page.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "category",
          "url"
        ],
        "type": "object"
      },
      "SnapchatPostSpecific": {
        "properties": {
          "embedded_text": {
            "description": "Text written on the Snap itself, where the poster's caption (text) is separate; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "generated_description": {
            "description": "A description Snapchat's own language model wrote for search, not the poster: it can be wrong about what the Snap shows. Null when Snapchat has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "generated_title": {
            "description": "A title Snapchat's own language model wrote for search, not the poster: it can be wrong about what the Snap shows. Null when Snapchat has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_attributed": {
            "description": "Snapchat names the account that posted it. False: it shows no account, so author holds only the label Snapchat shows instead.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "keywords": {
            "description": "Search keywords Snapchat derived from the Snap, not the poster's hashtags; [] if none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "lens": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SnapchatLensCredit"
              },
              {
                "type": "null"
              }
            ],
            "description": "The Lens it was made with; null when it credits none."
          },
          "place": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SnapchatPlaceCredit"
              },
              {
                "type": "null"
              }
            ],
            "description": "The place it was tagged at; null when it names none."
          },
          "recommend_count": {
            "description": "How many people recommended it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "sound": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SnapchatSound"
              },
              {
                "type": "null"
              }
            ],
            "description": "The sound it uses; null when it credits none."
          },
          "transcript": {
            "description": "What is said in the Snap, as Snapchat transcribed it, as plain text; null when it holds no speech or Snapchat has no transcript.",
            "type": [
              "string",
              "null"
            ]
          },
          "transcript_url": {
            "description": "Snapchat's timed transcript of the Snap, a WebVTT file; null when it has none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "recommend_count",
          "is_attributed",
          "embedded_text",
          "generated_title",
          "generated_description",
          "keywords",
          "transcript",
          "transcript_url",
          "sound",
          "lens",
          "place"
        ],
        "type": "object"
      },
      "SnapchatProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile",
            "description": "In Snapchat's words: `metrics.follower_count` is subscribers."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "SnapchatProfileSpecific": {
        "properties": {
          "category_id": {
            "description": "The category the account chose, as the platform identifies it (public-profile-category-v3-people).",
            "type": [
              "string",
              "null"
            ]
          },
          "highlights": {
            "description": "The Stories the account saved to its profile, with their Snaps: the first page of them, as the profile page holds it; [] if none.",
            "items": {
              "$ref": "#/components/schemas/SnapchatHighlight"
            },
            "type": "array"
          },
          "is_highlights_shown": {
            "description": "True when the profile shows saved Stories (story highlights), false when it shows none; null when unknown (no public profile).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_spotlights_public": {
            "description": "The page says the account has public Spotlights.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_story_live": {
            "description": "True when the Story the profile page plays holds a Snap under 24 hours old, false when it plays none or only older ones; null when unknown (no public profile, or Snaps that state no time).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "last_updated_at": {
            "description": "When the public profile last changed, as its page says, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "related_accounts": {
            "description": "Accounts the page recommends beside this one; [] if none.",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "snapcode_url": {
            "description": "Image of the account's Snapcode, the scannable code that adds it.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "spotlights": {
            "description": "The Spotlights the profile page shows, as it orders them: a sample, not the whole list; [] if none.",
            "items": {
              "$ref": "#/components/schemas/SnapchatSpotlightSummary"
            },
            "type": "array"
          },
          "story": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SnapchatStory"
              },
              {
                "type": "null"
              }
            ],
            "description": "The Story the profile page plays, its recent public Snaps, which can be days old (see is_story_live); null when it plays none."
          },
          "subcategory_id": {
            "description": "The subcategory the account chose, as the platform identifies it (public-profile-subcategory-v3-creator).",
            "type": [
              "string",
              "null"
            ]
          },
          "user_id": {
            "description": "The account's user ID, in the form comments name their authors with no public profile; id is its public profile's.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "user_id",
          "snapcode_url",
          "category_id",
          "subcategory_id",
          "is_story_live",
          "is_spotlights_public",
          "is_highlights_shown",
          "last_updated_at",
          "story",
          "highlights",
          "spotlights",
          "related_accounts"
        ],
        "type": "object"
      },
      "SnapchatSnap": {
        "properties": {
          "id": {
            "description": "The Snap's ID; null on a saved Story's Snaps, where the platform names none.",
            "type": [
              "string",
              "null"
            ]
          },
          "media_url": {
            "description": "The Snap's image or video file.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "posted_at": {
            "description": "When it was posted, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "preview_url": {
            "description": "A preview image of the Snap.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "image or video; null when the platform names another kind. New values may be added.",
            "enum": [
              "image",
              "video",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "media_url",
          "preview_url",
          "posted_at"
        ],
        "type": "object"
      },
      "SnapchatSound": {
        "properties": {
          "id": {
            "description": "Snapchat's ID of the sound.",
            "type": [
              "string",
              "null"
            ]
          },
          "subtitle": {
            "description": "Who or what the sound credits: the artist of a track, the username of the account that made an original sound, or the track an original sound contains. Null when it names no account.",
            "type": [
              "string",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "The sound's cover image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The sound's title (Original Sound for a poster's own).",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "subtitle",
          "thumbnail_url"
        ],
        "type": "object"
      },
      "SnapchatSpotlightMetrics": {
        "properties": {
          "comment_count": {
            "description": "Comments.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "like_count": {
            "description": "Likes (boosts, in the platform's data).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "recommend_count": {
            "description": "How many people recommended it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "share_count": {
            "description": "Shares.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "view_count": {
            "description": "Views.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "view_count",
          "like_count",
          "comment_count",
          "share_count",
          "recommend_count"
        ],
        "type": "object"
      },
      "SnapchatSpotlightResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "SnapchatSpotlightSummary": {
        "properties": {
          "caption": {
            "description": "The caption its poster wrote; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "duration_ms": {
            "description": "Its length in milliseconds.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "height": {
            "description": "Height in pixels.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "id": {
            "description": "The Spotlight's ID: what the Spotlight and comments endpoints take.",
            "type": "string"
          },
          "media_url": {
            "description": "Its video or image file.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/SnapchatSpotlightMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "published_at": {
            "description": "When it was posted, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "thumbnail_url": {
            "description": "Its cover image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "image or video; null when the platform names another kind. New values may be added.",
            "enum": [
              "image",
              "video",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The Spotlight's link.",
            "format": "uri",
            "type": "string"
          },
          "width": {
            "description": "Width in pixels.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "caption",
          "thumbnail_url",
          "type",
          "media_url",
          "published_at",
          "duration_ms",
          "width",
          "height",
          "metrics"
        ],
        "type": "object"
      },
      "SnapchatStory": {
        "properties": {
          "snaps": {
            "description": "The Story's Snaps, in the order it plays them.",
            "items": {
              "$ref": "#/components/schemas/SnapchatSnap"
            },
            "type": "array"
          },
          "thumbnail_url": {
            "description": "The Story's cover image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The Story's title; null when it has none.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "title",
          "thumbnail_url",
          "snaps"
        ],
        "type": "object"
      },
      "Sound": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform or parsed from display text (e.g. metrics.post_count from \"80K reels\"). A list path means the list may be incomplete. [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "author_name": {
            "description": "Who the platform credits for the sound: a track's artist(s) as one display string, or the creator's name for an original sound.",
            "type": [
              "string",
              "null"
            ]
          },
          "authors": {
            "description": "The platform accounts behind author_name (a track's artists, or the creator of an original sound), in the platform's order; [] when none is linked.",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "cover_url": {
            "description": "Cover art or thumbnail image URL. Platform CDN URLs can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "duration_ms": {
            "description": "Length of the audio the platform serves for the sound, in milliseconds (TikTok: the usable clip, often shorter than the full song).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native sound ID (string), the one in its page's URL; equals the ID a post's sound reference carries.",
            "type": "string"
          },
          "is_original": {
            "description": "An original sound a creator uploaded or recorded (false: a catalogue or licensed track).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/SoundMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "platform": {
            "description": "Platform ID (tiktok, instagram, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/SoundPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "play_url": {
            "description": "Audio file URL (a preview where the platform serves only one); signed links expire within hours; null when not exposed.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "streaming_links": {
            "description": "The same track on music streaming services, as the platform links it; [] when none (always for original sounds).",
            "items": {
              "$ref": "#/components/schemas/StreamingLink"
            },
            "type": "array"
          },
          "title": {
            "description": "Sound or track title as shown (an original sound's generated title, e.g. \"original sound - <name>\", included).",
            "type": [
              "string",
              "null"
            ]
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Canonical page of the sound, listing the posts that use it; null where the platform has none (Facebook).",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "platform",
          "id",
          "url",
          "title",
          "author_name",
          "authors",
          "is_original",
          "duration_ms",
          "cover_url",
          "play_url",
          "streaming_links",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "SoundMetrics": {
        "properties": {
          "post_count": {
            "description": "Posts using the sound (TikTok videos, Instagram and Facebook reels, YouTube Shorts), as the platform counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "post_count"
        ],
        "type": "object"
      },
      "SoundPlatformSpecific": {
        "properties": {
          "instagram": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InstagramSoundSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Instagram audio's own fields."
          },
          "tiktok": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokSoundSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A TikTok sound's own fields."
          }
        },
        "type": "object"
      },
      "SoundSummary": {
        "properties": {
          "author_name": {
            "description": "Who the platform credits for the sound (a track's artist, an original sound's creator), as the index's text names it; null when it does not.",
            "type": [
              "string",
              "null"
            ]
          },
          "cover_url": {
            "description": "Cover art URL; null until the result is filled. Platform CDN URLs can expire within hours.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native sound ID; null until the result is filled.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_original": {
            "description": "An original sound a creator uploaded, as the index's title says (\"original sound\"); null when the text does not say, until the result is filled.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/SoundMetrics",
            "description": "Counts as the index's text states them (\"80K reels\"; rounded, as old as the index's copy: see approximate_fields), or the platform's current ones once filled; null = not stated."
          },
          "title": {
            "description": "Sound or track title as the index's text shows it, else the words of the sound page's link (see approximate_fields); null when neither names it.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Canonical page of the sound (equals the result's url).",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "author_name",
          "is_original",
          "cover_url",
          "metrics"
        ],
        "type": "object"
      },
      "SoundcloudAlbumMetrics": {
        "properties": {
          "like_count": {
            "description": "Likes of the set (its tracks' likes are their own).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "repost_count": {
            "description": "Reposts of the set.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "like_count",
          "repost_count"
        ],
        "type": "object"
      },
      "SoundcloudAlbumSpecific": {
        "properties": {
          "embeddable_by": {
            "description": "Who may embed the player (all, me, none).",
            "type": [
              "string",
              "null"
            ]
          },
          "last_modified_at": {
            "description": "When the uploader last changed the set, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "license": {
            "description": "The license the set is published under (all-rights-reserved, cc-by, …).",
            "type": [
              "string",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/SoundcloudAlbumMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "permalink": {
            "description": "The set's name in its link (soundcloud.com/<artist>/sets/<permalink>).",
            "type": [
              "string",
              "null"
            ]
          },
          "published_at": {
            "description": "When the set went public on SoundCloud, RFC 3339 UTC; null when SoundCloud does not say.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "purchase_title": {
            "description": "The label of the buy link; null when SoundCloud's default is used.",
            "type": [
              "string",
              "null"
            ]
          },
          "purchase_url": {
            "description": "The buy link the uploader set; null when none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "tags": {
            "description": "The uploader's tags, without the quotes SoundCloud keeps around a tag of several words; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "uploaded_at": {
            "description": "When the set was created on SoundCloud, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "permalink",
          "tags",
          "license",
          "published_at",
          "uploaded_at",
          "last_modified_at",
          "embeddable_by",
          "purchase_url",
          "purchase_title",
          "metrics"
        ],
        "type": "object"
      },
      "SoundcloudArtistResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile",
            "description": "In SoundCloud's words: `metrics.post_count` is tracks SoundCloud states (not its list)."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "SoundcloudPostSpecific": {
        "properties": {
          "album_title": {
            "description": "The album in the release metadata; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "artist_name": {
            "description": "The credited artist in the release metadata, who may not be the account that uploaded it; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "author_follower_count": {
            "description": "The uploader's exact follower count.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "c_line": {
            "description": "The composition copyright line (©); null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "caption": {
            "description": "The short line the uploader wrote beside the track; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "download_count": {
            "description": "Downloads.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "embeddable_by": {
            "description": "Who may embed the player (all, me, none).",
            "type": [
              "string",
              "null"
            ]
          },
          "genre": {
            "description": "The genre the uploader chose, as written; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_commentable": {
            "description": "The uploader allows comments on the track.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_downloadable": {
            "description": "The uploader allows downloads of the track.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_explicit": {
            "description": "The release metadata marks the track explicit; null when it does not say.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_music": {
            "description": "The release metadata says the track holds music (false: spoken word or a podcast); null when it does not say.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_streamable": {
            "description": "SoundCloud lets the track be played.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "isrc": {
            "description": "International Standard Recording Code; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "label_name": {
            "description": "The record label the uploader credits; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "last_modified_at": {
            "description": "When the uploader last changed the track, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "license": {
            "description": "The license the track is published under (all-rights-reserved, cc-by, …).",
            "type": [
              "string",
              "null"
            ]
          },
          "monetization_model": {
            "description": "How the track earns in the United States (AD_SUPPORTED, SUB_HIGH_TIER, BLACKBOX, NOT_APPLICABLE); SoundCloud answers each country its own way. New values may be added.",
            "type": [
              "string",
              "null"
            ]
          },
          "p_line": {
            "description": "The sound recording copyright line (℗); null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "permalink": {
            "description": "The track's name in its link (soundcloud.com/<artist>/<permalink>).",
            "type": [
              "string",
              "null"
            ]
          },
          "policy": {
            "description": "What SoundCloud lets a logged-out listener in the United States do: ALLOW and MONETIZE play the whole track, SNIP a preview of it (see transcodings), BLOCK nothing. SoundCloud answers each country its own way: this is the US answer. New values may be added.",
            "type": [
              "string",
              "null"
            ]
          },
          "publisher": {
            "description": "The music publisher in the release metadata; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "purchase_title": {
            "description": "The label of the buy link; null when SoundCloud's default is used.",
            "type": [
              "string",
              "null"
            ]
          },
          "purchase_url": {
            "description": "The buy link the uploader set; null when none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "release_title": {
            "description": "The release in the release metadata; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "released_at": {
            "description": "The release date the uploader states, RFC 3339 UTC; it can be long before the track came to SoundCloud. Null when none.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "tags": {
            "description": "The uploader's tags, without the quotes SoundCloud keeps around a tag of several words; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "transcodings": {
            "description": "The encodings SoundCloud serves of the track to a logged-out listener in the United States, in its order; each country gets its own list. [] when none, as under policy BLOCK.",
            "items": {
              "$ref": "#/components/schemas/SoundcloudTranscoding"
            },
            "type": "array"
          },
          "upc": {
            "description": "The release's UPC or EAN barcode; null when none.",
            "type": [
              "string",
              "null"
            ]
          },
          "uploaded_at": {
            "description": "When the track was uploaded, RFC 3339 UTC; before published_at when its release was scheduled.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "visual_url": {
            "description": "The banner image the uploader set for the track's page; null when none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "waveform_url": {
            "description": "The JSON file of the track's waveform, which SoundCloud's player draws.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "writer_composer": {
            "description": "The writer or composer in the release metadata; null when none.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "genre",
          "tags",
          "caption",
          "permalink",
          "license",
          "label_name",
          "artist_name",
          "album_title",
          "release_title",
          "released_at",
          "uploaded_at",
          "last_modified_at",
          "isrc",
          "upc",
          "publisher",
          "writer_composer",
          "p_line",
          "c_line",
          "is_explicit",
          "is_music",
          "download_count",
          "is_downloadable",
          "is_streamable",
          "is_commentable",
          "policy",
          "monetization_model",
          "embeddable_by",
          "purchase_url",
          "purchase_title",
          "waveform_url",
          "visual_url",
          "transcodings",
          "author_follower_count"
        ],
        "type": "object"
      },
      "SoundcloudProfileSpecific": {
        "properties": {
          "first_name": {
            "description": "The first name the account gives; null when empty.",
            "type": [
              "string",
              "null"
            ]
          },
          "full_name": {
            "description": "The name the account gives besides its display name; null when empty.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_creator_mid_tier": {
            "description": "SoundCloud's mid-tier creator badge.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_pro": {
            "description": "SoundCloud's Pro badge.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_pro_unlimited": {
            "description": "SoundCloud's Pro Unlimited badge.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "last_modified_at": {
            "description": "When the account last changed its profile, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "last_name": {
            "description": "The last name the account gives; null when empty.",
            "type": [
              "string",
              "null"
            ]
          },
          "liked_playlist_count": {
            "description": "Playlists the account has liked (given, not received).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "liked_track_count": {
            "description": "Tracks the account has liked (given, not received), as SoundCloud counts them. The public list can hold fewer.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "plan": {
            "description": "The account's creator plan, as SoundCloud names it (free, creator-pro-unlimited, …). New values may be added.",
            "type": [
              "string",
              "null"
            ]
          },
          "playlist_count": {
            "description": "Playlists and albums, as SoundCloud counts them on the account's page. The public list can hold fewer.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "repost_count": {
            "description": "Tracks and playlists the account has reposted, when SoundCloud says; it usually leaves this empty for a logged-out reader: null.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "social_links": {
            "description": "The links the account lists on its profile, in its order, with SoundCloud's name for each and the email addresses among them; [] when none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/SoundcloudSocialLink"
            },
            "type": "array"
          }
        },
        "required": [
          "full_name",
          "first_name",
          "last_name",
          "playlist_count",
          "liked_track_count",
          "liked_playlist_count",
          "repost_count",
          "is_pro",
          "is_pro_unlimited",
          "is_creator_mid_tier",
          "plan",
          "last_modified_at",
          "social_links"
        ],
        "type": "object"
      },
      "SoundcloudSocialLink": {
        "properties": {
          "network": {
            "description": "SoundCloud's name for the service, lowercase: personal, instagram, facebook, twitter, youtube, soundcloud, spotify, email, support:patreon, other, … New values may be added.",
            "type": "string"
          },
          "title": {
            "description": "The label the account gave the link; null when it gave none.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The link as the account wrote it (https:// added when it had no scheme); an email address as a mailto: link.",
            "format": "uri",
            "type": "string"
          },
          "username": {
            "description": "The account on that service, as SoundCloud reads it from the link; null when it has none.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "network",
          "username",
          "title",
          "url"
        ],
        "type": "object"
      },
      "SoundcloudTrackResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post",
            "description": "In SoundCloud's words: `metrics.view_count` is plays."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "SoundcloudTracksResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), newest first. In SoundCloud's words: `metrics.view_count` is plays.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "SoundcloudTranscoding": {
        "properties": {
          "duration_ms": {
            "description": "Length of this encoding in milliseconds: the preview's on a snipped one.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_snipped": {
            "description": "Only a preview of the track, not all of it.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "mime_type": {
            "description": "The audio's media type.",
            "type": [
              "string",
              "null"
            ]
          },
          "preset": {
            "description": "SoundCloud's name of the encoding (aac_160k, mp3_1_0, abr_sq, …).",
            "type": [
              "string",
              "null"
            ]
          },
          "protocol": {
            "description": "How it is delivered: hls, progressive (one file), or cbc-encrypted-hls and ctr-encrypted-hls. New values may be added.",
            "type": [
              "string",
              "null"
            ]
          },
          "quality": {
            "description": "SoundCloud's quality label: lq (lower), sq (standard) or hq (high). New values may be added.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "preset",
          "protocol",
          "mime_type",
          "quality",
          "is_snipped",
          "duration_ms"
        ],
        "type": "object"
      },
      "SpotifyAlbumResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Album",
            "description": "In Spotify's words: `tracks[].metrics.view_count` is plays."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "SpotifyAlbumSpecific": {
        "properties": {
          "is_playable": {
            "description": "Spotify plays it in the country SocialTap asked from, which is not necessarily yours.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_pre_release": {
            "description": "Announced and not out yet.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "popularity": {
            "description": "Spotify's own score for this release, 0 to 100 and recent plays weighing most.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "pre_release_ends_at": {
            "description": "When a pre-release comes out, RFC 3339 UTC; null on a release that is out.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "release_date_precision": {
            "description": "How much of released_at Spotify states: day, month or year. New values may be added.",
            "enum": [
              "day",
              "month",
              "year",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "release_date_precision",
          "is_pre_release",
          "pre_release_ends_at",
          "is_playable",
          "popularity"
        ],
        "type": "object"
      },
      "SpotifyArtistResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "SpotifyArtistTrack": {
        "properties": {
          "album_id": {
            "description": "The ID of the release it is on, what spotify.album takes.",
            "type": [
              "string",
              "null"
            ]
          },
          "artist_name": {
            "description": "Who Spotify credits for the track, as one display string; null when the source names nobody.",
            "type": [
              "string",
              "null"
            ]
          },
          "artists": {
            "description": "The accounts of the track's credited artists, in Spotify's order; [] when the list names none (in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "cover_url": {
            "description": "The release's cover at its largest size.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "disc_number": {
            "description": "The disc of its release it is on; null where the list states none.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "duration_ms": {
            "description": "Exact length in milliseconds; null where the list states none.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "id": {
            "description": "The track's base62 ID, what spotify.track takes.",
            "type": "string"
          },
          "is_explicit": {
            "description": "True when Spotify marks the track explicit.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "play_count": {
            "description": "Plays, as Spotify counts them; null where the list states none or writes 0, which is no count.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "title": {
            "description": "The track's title.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The track's page.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "duration_ms",
          "artist_name",
          "play_count",
          "is_explicit",
          "disc_number",
          "album_id",
          "cover_url",
          "artists"
        ],
        "type": "object"
      },
      "SpotifyConcert": {
        "properties": {
          "city": {
            "description": "The venue's city.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Spotify's ID of the concert.",
            "type": "string"
          },
          "is_festival": {
            "description": "True for a festival.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "starts_at": {
            "description": "When it starts, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The concert's title, as Spotify shows it.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The concert's page.",
            "format": "uri",
            "type": "string"
          },
          "venue": {
            "description": "The venue's name.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "venue",
          "city",
          "starts_at",
          "is_festival"
        ],
        "type": "object"
      },
      "SpotifyCredit": {
        "properties": {
          "artist_id": {
            "description": "Their artist ID (spotify.artist takes it); null when they have no artist page.",
            "type": [
              "string",
              "null"
            ]
          },
          "group": {
            "description": "The heading Spotify lists it under (Composition & Lyrics, Production & Engineering, …).",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "Who, as Spotify names them.",
            "type": "string"
          },
          "role": {
            "description": "What they did, as Spotify says (Composer, Producer, Main Artist, …).",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "role",
          "group",
          "artist_id"
        ],
        "type": "object"
      },
      "SpotifyPinnedItem": {
        "properties": {
          "comment": {
            "description": "What the artist wrote with it; null when nothing.",
            "type": [
              "string",
              "null"
            ]
          },
          "image_url": {
            "description": "Its picture at its largest size.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "subtitle": {
            "description": "What the page writes under it, as shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "Its title.",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "What is pinned, in Spotify's word, lowercase (album, playlist, concert, …). New values may be added.",
            "type": [
              "string",
              "null"
            ]
          },
          "uri": {
            "description": "Its Spotify URI (spotify:album:…), of any kind.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "type",
          "uri",
          "title",
          "subtitle",
          "comment",
          "image_url"
        ],
        "type": "object"
      },
      "SpotifyPlaylistRef": {
        "properties": {
          "description": {
            "description": "The playlist's description as plain text; null when empty.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "The playlist's base62 ID, what spotify.playlist takes.",
            "type": "string"
          },
          "image_url": {
            "description": "The playlist's picture at its largest size.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "owner_name": {
            "description": "The name of the account that owns it, as Spotify shows it.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The playlist's name.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The playlist's page.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "description",
          "image_url",
          "owner_name"
        ],
        "type": "object"
      },
      "SpotifyPlaylistResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Playlist"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "SpotifyPlaylistSpecific": {
        "properties": {
          "created_at": {
            "description": "When it was created, RFC 3339 UTC; null on Spotify's own playlists, which don't state it.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "follower_count": {
            "description": "Listeners who follow the playlist, exact.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_algorithmic": {
            "description": "Whether Spotify marks it as assembled by its algorithm rather than by its editors; null where Spotify says neither, as on a listener's playlist or a chart.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_collaborative": {
            "description": "Whether people its owner invites can add to it.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_deleted_by_owner": {
            "description": "Whether its owner deleted it: Spotify goes on serving such a playlist to anyone with its link.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_user_created": {
            "description": "True for a listener's playlist, false for one of Spotify's own.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "updated_at": {
            "description": "When it last changed, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "follower_count",
          "is_collaborative",
          "is_algorithmic",
          "is_user_created",
          "is_deleted_by_owner",
          "created_at",
          "updated_at"
        ],
        "type": "object"
      },
      "SpotifyPlaylist_tracksResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 100), the playlist's own order, as its owner or Spotify arranged it. In Spotify's words: `metrics.view_count` is plays.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "SpotifyPodcastResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Podcast",
            "description": "In Spotify's words: `categories` is topics."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "SpotifyPodcast_episodesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the show's own order: newest first, or from the first episode on a show meant to be heard in order. In Spotify's words: `metrics.view_count` is plays.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "SpotifyPostSpecific": {
        "properties": {
          "added_at": {
            "description": "When it was added to the playlist listed, RFC 3339 UTC; null outside a playlist's list.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "added_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The listener who added it to the playlist listed: their username and page, and their name and picture when the source shows them; null outside a playlist's list and on Spotify's own lists, which name nobody."
          },
          "album_id": {
            "description": "The ID of the release it is on (spotify.album takes it); null when the source does not show it, as on the embed page.",
            "type": [
              "string",
              "null"
            ]
          },
          "album_title": {
            "description": "The title of that release.",
            "type": [
              "string",
              "null"
            ]
          },
          "album_track_count": {
            "description": "How many tracks that release has.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "album_type": {
            "description": "What kind of release that is, as Spotify says. New values may be added; treat unknown values as album.",
            "enum": [
              "album",
              "single",
              "ep",
              "compilation",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "album_url": {
            "description": "That release's page.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "bpm": {
            "description": "Its tempo in beats per minute, to two decimals, as Spotify measured it; null where the source does not show it, as everywhere but a playlist's list.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "camelot_key": {
            "description": "Its key on the Camelot wheel DJs mix by (6A); null where the source does not show it, as everywhere but a playlist's list.",
            "type": [
              "string",
              "null"
            ]
          },
          "canonical_track_id": {
            "description": "The ID Spotify treats as this recording's main one, when that is another; null when this is it or the source does not show it.",
            "type": [
              "string",
              "null"
            ]
          },
          "copyrights": {
            "description": "The copyright lines of the release it is on; [] when none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/AlbumCopyright"
            },
            "type": "array"
          },
          "credits": {
            "description": "Who wrote, performed and produced it, as Spotify's Credits panel lists them; [] when none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/SpotifyCredit"
            },
            "type": "array"
          },
          "disc_number": {
            "description": "The disc of that release it is on, from 1.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_explicit": {
            "description": "Spotify marks it explicit.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_paywalled": {
            "description": "An episode only subscribers can hear in full; null on a track.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_playable": {
            "description": "Spotify plays it in the country SocialTap asked from, which is not necessarily yours.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "isrc": {
            "description": "International Standard Recording Code, 12 characters without hyphens; null when the source does not show it.",
            "type": [
              "string",
              "null"
            ]
          },
          "label": {
            "description": "The record label of the release it is on; null when the source does not show it.",
            "type": [
              "string",
              "null"
            ]
          },
          "languages": {
            "description": "The languages it is performed in, as Spotify's tags; [] when none is stated (listed in unknown_fields when the source cannot see them).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "music_video_count": {
            "description": "How many music videos Spotify links to it; null when the source does not show it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "musical_key": {
            "description": "Its key and mode as Spotify measured them (F# minor); null where the source does not show it, as everywhere but a playlist's list.",
            "type": [
              "string",
              "null"
            ]
          },
          "playability_reason": {
            "description": "Why, as Spotify says it (playable, country_restricted, …), for that country; null when the source does not say.",
            "type": [
              "string",
              "null"
            ]
          },
          "podcast_id": {
            "description": "An episode's show (spotify.podcast takes it); null on a track.",
            "type": [
              "string",
              "null"
            ]
          },
          "popularity": {
            "description": "Spotify's own score for this track ID, 0 to 100 and recent plays weighing most; two IDs of one recording score apart (canonical_track_id).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "release_date_precision": {
            "description": "How much of published_at Spotify states: day, month or year. Null for an episode, whose time is exact, and when the source does not say. New values may be added.",
            "enum": [
              "day",
              "month",
              "year",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "track_number": {
            "description": "Its position on that disc, from 1.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "album_id",
          "album_title",
          "album_url",
          "album_type",
          "album_track_count",
          "release_date_precision",
          "disc_number",
          "track_number",
          "isrc",
          "label",
          "copyrights",
          "credits",
          "is_explicit",
          "is_playable",
          "playability_reason",
          "popularity",
          "languages",
          "music_video_count",
          "canonical_track_id",
          "added_at",
          "added_by",
          "bpm",
          "musical_key",
          "camelot_key",
          "podcast_id",
          "is_paywalled"
        ],
        "type": "object"
      },
      "SpotifyProfileSpecific": {
        "properties": {
          "active_decades": {
            "description": "The decades Spotify lists the artist as active in, as their first year (1980), in its order; [] when it lists none.",
            "items": {
              "format": "int64",
              "type": "integer"
            },
            "type": "array"
          },
          "ai_persona": {
            "description": "Spotify's word when it labels the artist an AI persona (confirmed), lowercase; null when it says nothing, which is nearly always. New values may be added.",
            "type": [
              "string",
              "null"
            ]
          },
          "albums": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SpotifyReleases"
              },
              {
                "type": "null"
              }
            ],
            "description": "The artist's albums, newest first."
          },
          "appears_on": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SpotifyReleases"
              },
              {
                "type": "null"
              }
            ],
            "description": "Other artists' releases the artist appears on."
          },
          "biography_type": {
            "description": "Spotify's word for the kind of text bio is (autobiography, biography, …), lowercase. New values may be added.",
            "type": [
              "string",
              "null"
            ]
          },
          "compilations": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SpotifyReleases"
              },
              {
                "type": "null"
              }
            ],
            "description": "The artist's compilations, newest first."
          },
          "concert_count": {
            "description": "How many concerts Spotify counts for the artist, which concerts can hold fewer of.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "concerts": {
            "description": "The artist's upcoming concerts Spotify lists, as many as the page shows, which can depend on the country SocialTap asked from; [] when it lists none.",
            "items": {
              "$ref": "#/components/schemas/SpotifyConcert"
            },
            "type": "array"
          },
          "discovered_on": {
            "description": "Playlists where listeners discovered the artist, as many as the page shows, which can be fewer than discovered_on_count says: Spotify answers some of them with an error, and they are left out. [] when none.",
            "items": {
              "$ref": "#/components/schemas/SpotifyPlaylistRef"
            },
            "type": "array"
          },
          "discovered_on_count": {
            "description": "How many playlists Spotify counts as where listeners discovered the artist, at most a hundred on the artists sampled.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "featured_in": {
            "description": "Playlists Spotify lists as featuring the artist, as many as the page shows; [] when it lists none.",
            "items": {
              "$ref": "#/components/schemas/SpotifyPlaylistRef"
            },
            "type": "array"
          },
          "featured_in_count": {
            "description": "How many playlists Spotify counts as featuring the artist, which featured_in can hold fewer of.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "gallery_urls": {
            "description": "The pictures in the artist's gallery, each at its largest size; [] when it has none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "is_registered": {
            "description": "True when Spotify says the artist's profile is registered with it, which is_verified's badge need not be.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "latest_release": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SpotifyRelease"
              },
              {
                "type": "null"
              }
            ],
            "description": "The artist's latest release; null when it has none or Spotify does not name one."
          },
          "monthly_listener_count": {
            "description": "People who played the artist in the last 28 days, exact, as Spotify counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "music_video_count": {
            "description": "How many music videos Spotify counts for the artist, which music_videos can hold fewer of.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "music_videos": {
            "description": "The artist's music videos, as many as the page holds; [] when it holds none. Spotify states no length or plays for them here.",
            "items": {
              "$ref": "#/components/schemas/SpotifyArtistTrack"
            },
            "type": "array"
          },
          "pinned_item": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SpotifyPinnedItem"
              },
              {
                "type": "null"
              }
            ],
            "description": "What the artist has pinned to the top of its page; null when nothing."
          },
          "playlist_count": {
            "description": "How many playlists Spotify counts on the artist's page, which playlists can hold fewer of.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "playlists": {
            "description": "The playlists the artist shows on its page; [] when it shows none.",
            "items": {
              "$ref": "#/components/schemas/SpotifyPlaylistRef"
            },
            "type": "array"
          },
          "popular_release_count": {
            "description": "How many popular releases Spotify counts, which popular_releases can hold fewer of.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "popular_releases": {
            "description": "The artist's popular releases, as the page ranks them and as many as it shows; [] when it shows none.",
            "items": {
              "$ref": "#/components/schemas/SpotifyRelease"
            },
            "type": "array"
          },
          "popularity": {
            "description": "Spotify's popularity score of the artist, 0 to 100.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "related_artist_count": {
            "description": "How many related artists Spotify counts, which related_artists can hold fewer of.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "related_artists": {
            "description": "Artists fans of this one also like, as many as the page shows; [] when it shows none.",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "singles": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SpotifyReleases"
              },
              {
                "type": "null"
              }
            ],
            "description": "The artist's singles and EPs, newest first."
          },
          "top_cities": {
            "description": "The cities with the most monthly listeners, most first, as many as Spotify shows; [] when it shows none.",
            "items": {
              "$ref": "#/components/schemas/SpotifyTopCity"
            },
            "type": "array"
          },
          "top_tracks": {
            "description": "The tracks the artist's page lists as popular, in its order; [] when it lists none. spotify.track answers each in full.",
            "items": {
              "$ref": "#/components/schemas/SpotifyArtistTrack"
            },
            "type": "array"
          },
          "world_rank": {
            "description": "The artist's place in Spotify's worldwide ranking by monthly listeners, 1 the top; null for an artist outside the ranking, where Spotify writes 0.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "monthly_listener_count",
          "world_rank",
          "popularity",
          "is_registered",
          "biography_type",
          "active_decades",
          "gallery_urls",
          "top_cities",
          "top_tracks",
          "music_videos",
          "music_video_count",
          "latest_release",
          "popular_releases",
          "popular_release_count",
          "albums",
          "singles",
          "compilations",
          "appears_on",
          "related_artists",
          "related_artist_count",
          "concerts",
          "concert_count",
          "playlists",
          "playlist_count",
          "featured_in",
          "featured_in_count",
          "discovered_on",
          "discovered_on_count",
          "pinned_item",
          "ai_persona"
        ],
        "type": "object"
      },
      "SpotifyRelease": {
        "properties": {
          "artists": {
            "description": "The release's credited artists where the list names them (appears_on); [] elsewhere, where they are the artist's own.",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "cover_url": {
            "description": "The cover at its largest size.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "The release's base62 ID, what spotify.album takes.",
            "type": "string"
          },
          "label": {
            "description": "The record label, as Spotify writes it; null where the list does not say.",
            "type": [
              "string",
              "null"
            ]
          },
          "release_date_precision": {
            "description": "How much of released_at Spotify states: day, month or year. New values may be added.",
            "enum": [
              "day",
              "month",
              "year",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "released_at": {
            "description": "Its release date at midnight UTC: Spotify states no time, and release_date_precision says when it states only a month or a year (the first of it, then).",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The release's title, as Spotify shows it.",
            "type": [
              "string",
              "null"
            ]
          },
          "track_count": {
            "description": "How many tracks the release has; null where the list does not say.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "type": {
            "description": "What kind of release it is, as Spotify says: album, single, ep or compilation. New values may be added.",
            "enum": [
              "album",
              "single",
              "ep",
              "compilation",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The release's page.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "type",
          "released_at",
          "release_date_precision",
          "cover_url",
          "track_count",
          "label",
          "artists"
        ],
        "type": "object"
      },
      "SpotifyReleases": {
        "properties": {
          "ids": {
            "description": "Every release ID Spotify's metadata record lists for the section, those in items included, each what spotify.album takes. One release can have several, its editions for different countries, so this can list more than total_count. [] when it lists none, or when the record could not be read (then named in partial_data).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "items": {
            "description": "The releases the artist's page shows; [] when it shows none.",
            "items": {
              "$ref": "#/components/schemas/SpotifyRelease"
            },
            "type": "array"
          },
          "total_count": {
            "description": "How many releases Spotify counts in the section, which items can hold fewer of.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "total_count",
          "items",
          "ids"
        ],
        "type": "object"
      },
      "SpotifySearch_albumsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 100), Spotify's own ranking for the query. In Spotify's words: `tracks[].metrics.view_count` is plays.",
            "items": {
              "$ref": "#/components/schemas/Album"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "SpotifySearch_artistsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 100), Spotify's own ranking for the query.",
            "items": {
              "$ref": "#/components/schemas/Profile"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "SpotifySearch_playlistsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 100), Spotify's own ranking for the query.",
            "items": {
              "$ref": "#/components/schemas/Playlist"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "SpotifySearch_podcastsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 100), Spotify's own ranking for the query. In Spotify's words: `categories` is topics.",
            "items": {
              "$ref": "#/components/schemas/Podcast"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "SpotifySearch_tracksResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 100), Spotify's own ranking for the query. In Spotify's words: `metrics.view_count` is plays.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "SpotifyTopCity": {
        "properties": {
          "city": {
            "description": "The city's name, as Spotify writes it.",
            "type": [
              "string",
              "null"
            ]
          },
          "country_code": {
            "description": "The city's country, an ISO 3166-1 alpha-2 code.",
            "type": [
              "string",
              "null"
            ]
          },
          "listener_count": {
            "description": "Monthly listeners in the city, exact.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "region": {
            "description": "The region of the country, as Spotify codes it (ENG, CMX).",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "city",
          "country_code",
          "region",
          "listener_count"
        ],
        "type": "object"
      },
      "SpotifyTrackResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post",
            "description": "In Spotify's words: `metrics.view_count` is plays."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "StreamingLink": {
        "properties": {
          "service": {
            "description": "The streaming service. New values may be added; treat unknown values as other.",
            "enum": [
              "spotify",
              "apple_music"
            ],
            "type": "string"
          },
          "url": {
            "description": "The track's public page on the service.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "service",
          "url"
        ],
        "type": "object"
      },
      "Suggestion": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded or capped by the platform (hashtag.metrics.post_count at Instagram's ceiling). [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "hashtag": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/HashtagRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The hashtag a hashtag suggestion names, keyed as the platform's hashtag endpoints key it; null for every other type."
          },
          "platform": {
            "description": "Platform whose search box offers the suggestion.",
            "examples": [
              "tiktok"
            ],
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/SuggestionPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "position": {
            "description": "Zero-based rank of the suggestion in the list, counting every type: the platform's order (each endpoint's notes say how a list combining several of the platform's searches is ordered).",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "profile": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The account a profile suggestion names; null for every other type."
          },
          "text": {
            "description": "The suggestion as the platform shows it, whitespace-trimmed: the completed search for a query suggestion, the account's name for a profile one, the domain for a website one.",
            "examples": [
              "dogs funny videos"
            ],
            "type": "string"
          },
          "type": {
            "description": "query = a completed search to run; profile = an account (or community) the platform proposes, described in profile; hashtag = a hashtag, described in hashtag; website = a website the platform proposes: text is its domain (nike.com), as the platform's searches by website take it. New values may be added.",
            "enum": [
              "query",
              "profile",
              "hashtag",
              "website"
            ],
            "type": "string"
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none; [] when every list is known (a suggestion has none yet).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Where the suggestion leads on the platform: the search results page for a query, the account's page for a profile, the hashtag's page for a hashtag, the platform's page for the website for a website.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "text",
          "type",
          "position",
          "url",
          "profile",
          "hashtag",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "SuggestionPlatformSpecific": {
        "properties": {
          "google": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/GoogleSuggestionSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Google Ads Transparency Center suggestion's own fields."
          },
          "instagram": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InstagramSuggestionSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Instagram suggestion's own fields."
          },
          "tiktok": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokSuggestionSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A TikTok suggestion's own fields."
          }
        },
        "type": "object"
      },
      "TelegramButton": {
        "properties": {
          "text": {
            "description": "The button's label.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "What it opens: a web link or a tg:// link.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "text",
          "url"
        ],
        "type": "object"
      },
      "TelegramChannelResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile",
            "description": "In Telegram's words: `metrics.follower_count` is subscribers."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TelegramChannel_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 20), newest first. In Telegram's words: `metrics.like_count` is reactions.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TelegramDocument": {
        "properties": {
          "performer": {
            "description": "An audio file's performer as Telegram shows it; null for other files and an audio file without one.",
            "type": [
              "string",
              "null"
            ]
          },
          "size": {
            "description": "Its size as Telegram shows it (1.3 MB); null when it shows none, as on an audio file.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The file's name, or an audio file's title.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "title",
          "performer",
          "size"
        ],
        "type": "object"
      },
      "TelegramForward": {
        "properties": {
          "author": {
            "description": "The admin who signed the original; null when unsigned.",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "The name of the channel or person it was forwarded from; null when Telegram leaves it blank.",
            "type": [
              "string",
              "null"
            ]
          },
          "post_id": {
            "description": "The original post's id, when the link names one.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The original's link (or the account's, for a person); null when the source hides itself.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "url",
          "post_id",
          "author"
        ],
        "type": "object"
      },
      "TelegramLinkPreview": {
        "properties": {
          "description": {
            "description": "The page's description, as the card shows it.",
            "type": [
              "string",
              "null"
            ]
          },
          "image_url": {
            "description": "The card's image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "site_name": {
            "description": "The site's name.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The page's title.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The previewed link.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "url",
          "site_name",
          "title",
          "description",
          "image_url"
        ],
        "type": "object"
      },
      "TelegramPoll": {
        "properties": {
          "options": {
            "description": "The options, in the poll's order.",
            "items": {
              "$ref": "#/components/schemas/TelegramPollOption"
            },
            "type": "array"
          },
          "question": {
            "description": "The question.",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "Telegram's label, lower case: anonymous poll, public poll, anonymous quiz, …",
            "type": [
              "string",
              "null"
            ]
          },
          "voter_count": {
            "description": "People who voted; rounded by Telegram from the thousands up (see approximate_fields).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "question",
          "type",
          "voter_count",
          "options"
        ],
        "type": "object"
      },
      "TelegramPollOption": {
        "properties": {
          "percent": {
            "description": "Its share of the votes, in percent, as Telegram rounds it.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "text": {
            "description": "The option's text.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "text",
          "percent"
        ],
        "type": "object"
      },
      "TelegramPostResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post",
            "description": "In Telegram's words: `metrics.like_count` is reactions."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TelegramPostSpecific": {
        "properties": {
          "buttons": {
            "description": "The buttons under the post that open a link; [] when none.",
            "items": {
              "$ref": "#/components/schemas/TelegramButton"
            },
            "type": "array"
          },
          "channel_id": {
            "description": "Telegram's numeric ID of the channel or group the message is in, which stays when its username changes.",
            "type": [
              "string",
              "null"
            ]
          },
          "document": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TelegramDocument"
              },
              {
                "type": "null"
              }
            ],
            "description": "The file or audio file the post carries, which Telegram names but does not link logged out; null when none."
          },
          "forwarded_from": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TelegramForward"
              },
              {
                "type": "null"
              }
            ],
            "description": "Where the post was forwarded from; null when it was not forwarded."
          },
          "is_edited": {
            "description": "Whether the post shows as edited.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "link_preview": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TelegramLinkPreview"
              },
              {
                "type": "null"
              }
            ],
            "description": "The link preview card the post shows; null when none."
          },
          "links": {
            "description": "The link targets in the post's text, in order, those behind a word included; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "message_id": {
            "description": "The message's number within its channel or group: the last part of its link.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "poll": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TelegramPoll"
              },
              {
                "type": "null"
              }
            ],
            "description": "The poll the post carries; null when none."
          },
          "reactions": {
            "description": "The reactions the post shows, each emoji with its count; [] when it shows none. Their sum is metrics.like_count.",
            "items": {
              "$ref": "#/components/schemas/TelegramReaction"
            },
            "type": "array"
          },
          "reply_to": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TelegramReply"
              },
              {
                "type": "null"
              }
            ],
            "description": "The message this post replies to, as its preview bar shows it; null when it is not a reply."
          },
          "sender_name": {
            "description": "The name of the group member who sent the message, when they have no username: author is then the group. Null otherwise.",
            "type": [
              "string",
              "null"
            ]
          },
          "signature": {
            "description": "The name of the admin who signed the post, on a channel that signs its posts; null when unsigned.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "message_id",
          "channel_id",
          "signature",
          "sender_name",
          "is_edited",
          "forwarded_from",
          "reply_to",
          "reactions",
          "link_preview",
          "poll",
          "document",
          "links",
          "buttons"
        ],
        "type": "object"
      },
      "TelegramProfileSpecific": {
        "properties": {
          "account_type": {
            "description": "What Telegram's page shows the account to be: channel, group, user or bot. New values may be added.",
            "enum": [
              "channel",
              "group",
              "user",
              "bot",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "channel_id": {
            "description": "Telegram's numeric ID of the channel, which stays when its username changes. Null when the channel's preview shows none (its first message was deleted, or it serves no preview), and for a group, a user or a bot.",
            "type": [
              "string",
              "null"
            ]
          },
          "file_count": {
            "description": "Files the channel has posted, as its preview's panel shows it; null when it shows none.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_preview_available": {
            "description": "Whether t.me served this channel's public preview (t.me/s/<name>, where telegram.channel_posts reads its posts) from where this request left: it is off on some channels, and Telegram withholds some only in certain countries. False for a group, a user or a bot. Null when the request for the preview failed (a partial_data warning).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "link_count": {
            "description": "Links the channel has posted, as its preview's panel shows it; null when it shows none.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "monthly_user_count": {
            "description": "A bot's monthly users, as its page shows them; null otherwise.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "online_count": {
            "description": "Members online now, on a group that shows it; null otherwise.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "photo_count": {
            "description": "Photos the channel has posted, as its preview's panel shows it; null when it shows none.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "video_count": {
            "description": "Videos the channel has posted, as its preview's panel shows it; null when it shows none.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "account_type",
          "channel_id",
          "is_preview_available",
          "online_count",
          "monthly_user_count",
          "photo_count",
          "video_count",
          "link_count",
          "file_count"
        ],
        "type": "object"
      },
      "TelegramReaction": {
        "properties": {
          "count": {
            "description": "How many; rounded by Telegram from the thousands up (see approximate_fields).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "custom_emoji_id": {
            "description": "The custom emoji's ID; null for a unicode one.",
            "type": [
              "string",
              "null"
            ]
          },
          "emoji": {
            "description": "The unicode emoji; null for a custom emoji or Telegram Stars.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_paid": {
            "description": "Whether it is a paid reaction (Telegram Stars).",
            "type": [
              "boolean",
              "null"
            ]
          }
        },
        "required": [
          "emoji",
          "custom_emoji_id",
          "is_paid",
          "count"
        ],
        "type": "object"
      },
      "TelegramReply": {
        "properties": {
          "author": {
            "description": "The name the bar shows; null when it shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "post_id": {
            "description": "The replied-to post's id, when the link names one.",
            "type": [
              "string",
              "null"
            ]
          },
          "text": {
            "description": "The snippet the bar shows, often cut short.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The replied-to message's link; null when the bar has none.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "url",
          "post_id",
          "author",
          "text"
        ],
        "type": "object"
      },
      "TelegramSearch_channelsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "ThreadsCommentSpecific": {
        "properties": {
          "language": {
            "description": "The reply's language as Threads detected it, a BCP-47 tag (en, pt, zh-TW); null when Threads could not tell (an emoji, a link, media only) or does not say.",
            "type": [
              "string",
              "null"
            ]
          },
          "quote_count": {
            "description": "Times the reply was quoted in another post; never negative.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "repost_count": {
            "description": "Times the reply was reposted; never negative.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "repost_count",
          "quote_count",
          "language"
        ],
        "type": "object"
      },
      "ThreadsCommentsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), newest first.",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "ThreadsHashtagSpecific": {
        "properties": {
          "is_community": {
            "description": "The tag is a Threads community (\"NBA Threads\"), not a plain tag.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "recent_post_count": {
            "description": "Recent posts with the tag as Threads counts them (it does not state the window), rounded (in approximate_fields).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "is_community",
          "recent_post_count"
        ],
        "type": "object"
      },
      "ThreadsLink": {
        "properties": {
          "image_url": {
            "description": "The card's image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The card's headline.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The linked page (Threads' l.threads.com redirect removed).",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "url",
          "title",
          "image_url"
        ],
        "type": "object"
      },
      "ThreadsPostResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "ThreadsPostSpecific": {
        "properties": {
          "is_edited": {
            "description": "The text was edited after posting.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_reply": {
            "description": "The post is a reply to another post.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_spoiler": {
            "description": "The author marked the media as a spoiler.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "link": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ThreadsLink"
              },
              {
                "type": "null"
              }
            ],
            "description": "The link preview card the post shows; null when none."
          },
          "numeric_id": {
            "description": "Threads' numeric post ID, which the shortcode in id encodes.",
            "type": [
              "string",
              "null"
            ]
          },
          "quoted_post": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ThreadsQuotedPost"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post this one quotes; null when it quotes none, or when the quoted post is no longer available (deleted, or not shown logged out)."
          },
          "reply_control": {
            "description": "Who may reply, as Threads names it (everyone, accounts_you_follow, mentioned_only, …).",
            "type": [
              "string",
              "null"
            ]
          },
          "reply_to_author": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The author of the post this one replies to; null when it is not a reply."
          },
          "topic_tag": {
            "description": "The topic or community tag shown on the post; null when none.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "numeric_id",
          "is_reply",
          "reply_to_author",
          "quoted_post",
          "topic_tag",
          "link",
          "reply_control",
          "is_spoiler",
          "is_edited"
        ],
        "type": "object"
      },
      "ThreadsPostsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 25), newest first.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "ThreadsProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "ThreadsProfileSpecific": {
        "properties": {
          "interest_tags": {
            "description": "Topic labels Threads shows on the profile, as shown; [] when it shows none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "verified_link_urls": {
            "description": "The external_links URLs Threads marks as verified, in the same form; [] when none is marked (listed in unknown_fields when the source cannot see the links).",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "interest_tags",
          "verified_link_urls"
        ],
        "type": "object"
      },
      "ThreadsQuotedPost": {
        "properties": {
          "author": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "Its author."
          },
          "id": {
            "description": "Its shortcode.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Its URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "author"
        ],
        "type": "object"
      },
      "ThreadsSearch_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 20), newest first with sort=newest, Threads' best matches (its search ranking) with sort=relevance.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "ThreadsSearch_profilesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 100), Threads' search ranking.",
            "items": {
              "$ref": "#/components/schemas/Profile"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TikTokAdCountryTargeting": {
        "properties": {
          "age_ranges": {
            "description": "Age ranges targeted (13-17, 18-24, 25-34, 35-44, 45-54, 55+); [] when not shown.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "breakdown": {
            "description": "Unique users reached there by age range and gender, the segments TikTok shows a number for; [] when none.",
            "items": {
              "$ref": "#/components/schemas/TikTokAdReachSegment"
            },
            "type": "array"
          },
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country code.",
            "type": "string"
          },
          "genders": {
            "description": "Genders targeted (female, male, unknown); [] when not shown.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "reach": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Range"
              },
              {
                "type": "null"
              }
            ],
            "description": "Unique users the ad reached there (rounded: approximate_fields); null when not shown."
          }
        },
        "required": [
          "country_code",
          "reach",
          "age_ranges",
          "genders",
          "breakdown"
        ],
        "type": "object"
      },
      "TikTokAdReachSegment": {
        "properties": {
          "age_range": {
            "description": "Age range (18-24, 55+).",
            "type": "string"
          },
          "gender": {
            "description": "female, male or unknown.",
            "type": "string"
          },
          "reach": {
            "$ref": "#/components/schemas/Range",
            "description": "Unique users reached (rounded: approximate_fields)."
          }
        },
        "required": [
          "age_range",
          "gender",
          "reach"
        ],
        "type": "object"
      },
      "TikTokAdSpecific": {
        "properties": {
          "advertiser_business_id": {
            "description": "The advertiser's TikTok business ID (search_ads advertiser_id).",
            "type": [
              "string",
              "null"
            ]
          },
          "advertiser_registry_location": {
            "description": "Where the advertiser is registered (Italy).",
            "type": [
              "string",
              "null"
            ]
          },
          "budget": {
            "description": "Creative Center's budget level; null off the board. New values may be added; treat unknown values as other.",
            "enum": [
              "low",
              "medium",
              "high",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "category": {
            "description": "The ad's topic as TikTok files it (Apps, Food & Beverage).",
            "type": [
              "string",
              "null"
            ]
          },
          "ctr_top_percent": {
            "description": "Click-through rate rank: the ad is in the top this many percent of ads (4 = top 4%); null off the board.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "is_removed": {
            "description": "TikTok took the ad down (its rules or local law), in some or all regions.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "like_count": {
            "description": "Likes the ad drew, as Creative Center counts them; null off the board.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "objective": {
            "description": "The campaign objective (Reach, Traffic).",
            "type": [
              "string",
              "null"
            ]
          },
          "rank": {
            "description": "Place on Creative Center's Top Ads board, 1 first; null off the board.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "removal_country_codes": {
            "description": "Countries where TikTok took the ad down (ISO 3166-1 alpha-2); [] when it was not taken down (in unknown_fields when not shown).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "removal_reasons": {
            "description": "TikTok's reasons for the takedown; [] when none (in unknown_fields when not shown).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "targeting": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokAdTargeting"
              },
              {
                "type": "null"
              }
            ],
            "description": "Whom the advertiser targeted and whom the ad reached, per country; null when not shown."
          }
        },
        "required": [
          "is_removed",
          "removal_reasons",
          "category",
          "objective",
          "removal_country_codes",
          "targeting",
          "advertiser_business_id",
          "advertiser_registry_location",
          "rank",
          "like_count",
          "ctr_top_percent",
          "budget"
        ],
        "type": "object"
      },
      "TikTokAdTargeting": {
        "properties": {
          "cities": {
            "description": "Cities targeted; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "countries": {
            "description": "Per country it ran in: the ages and genders targeted and the unique users reached.",
            "items": {
              "$ref": "#/components/schemas/TikTokAdCountryTargeting"
            },
            "type": "array"
          },
          "creator_interactions": {
            "description": "Creator interaction categories targeted; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "device_models": {
            "description": "Device models targeted; [] when any.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "interests": {
            "description": "Interest categories targeted; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "is_audience_excluded": {
            "description": "The advertiser excluded a custom audience.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_custom_audience": {
            "description": "The advertiser targeted a custom audience (its own customer list or a lookalike).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_high_spending_power": {
            "description": "Targeted at users TikTok rates as high spenders.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "operating_systems": {
            "description": "Operating systems targeted; [] when any.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "provinces": {
            "description": "Provinces or states targeted within the countries; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "video_interactions": {
            "description": "Video interaction categories targeted; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "countries",
          "interests",
          "video_interactions",
          "creator_interactions",
          "provinces",
          "cities",
          "device_models",
          "operating_systems",
          "is_custom_audience",
          "is_audience_excluded",
          "is_high_spending_power"
        ],
        "type": "object"
      },
      "TikTokCommentSpecific": {
        "properties": {
          "author_sec_uid": {
            "description": "The commenter's secUid, TikTok's account key that survives a rename.",
            "type": [
              "string",
              "null"
            ]
          },
          "language": {
            "description": "The comment's language as TikTok detected it, an ISO 639-1 code (en, fr); null when TikTok could not tell (emoji, a name) or does not say.",
            "type": [
              "string",
              "null"
            ]
          },
          "thread_id": {
            "description": "For a reply: the ID of its top-level comment (parent_id may name another reply it answers); null for a top-level comment.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "author_sec_uid",
          "language",
          "thread_id"
        ],
        "type": "object"
      },
      "TikTokDownloadSpecific": {
        "properties": {
          "is_download_allowed": {
            "description": "The creator lets viewers save the post in TikTok's app; false: saving is turned off (the files stay public). Null when TikTok does not say.",
            "type": [
              "boolean",
              "null"
            ]
          }
        },
        "required": [
          "is_download_allowed"
        ],
        "type": "object"
      },
      "TikTokEffectSpecific": {
        "properties": {
          "creator_sec_uid": {
            "description": "The creator's secUid, TikTok's account key that survives a rename; null for TikTok's own effects.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "creator_sec_uid"
        ],
        "type": "object"
      },
      "TikTokHashtagSpecific": {
        "properties": {
          "banner_url": {
            "description": "The hashtag page's cover image URL; null when it has none. TikTok CDN URLs can expire.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "industry": {
            "description": "The industry Creative Center files the hashtag under (Apparel & Accessories, Games, …), as shown; not normalized.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_new_to_board": {
            "description": "First time on the board this period; null off a board.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_promoted": {
            "description": "An advertiser's hashtag: a Branded Hashtag Challenge, or one Creative Center marks promoted.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "period_post_count": {
            "description": "Posts with the tag published in the board's period (the request's window); null off a board.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "period_view_count": {
            "description": "Views in the board's period of posts with the tag; null off a board.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "rank": {
            "description": "Position on the requested trending board (1 = most popular; the request's country, period and industry); null off a board.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "rank_change": {
            "description": "Places climbed since the previous period (negative: fell, 0: unchanged); null when new to the board or off a board.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "trend": {
            "description": "The hashtag's popularity over the board's period, oldest first; [] off a board (in unknown_fields).",
            "items": {
              "$ref": "#/components/schemas/TikTokHashtagTrendPoint"
            },
            "type": "array"
          },
          "view_count": {
            "description": "Views across every post carrying the tag, all time, exact; null where TikTok does not show it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "view_count",
          "banner_url",
          "is_promoted",
          "rank",
          "rank_change",
          "is_new_to_board",
          "period_post_count",
          "period_view_count",
          "industry",
          "trend"
        ],
        "type": "object"
      },
      "TikTokHashtagTrendPoint": {
        "properties": {
          "popularity": {
            "description": "Popularity in the interval relative to the period's peak, 0 to 1, as Creative Center scales it.",
            "format": "double",
            "maximum": 1,
            "minimum": 0,
            "type": "number"
          },
          "start_at": {
            "description": "Start of the interval (a day on TikTok's boards), RFC 3339 UTC.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "start_at",
          "popularity"
        ],
        "type": "object"
      },
      "TikTokLiveSpecific": {
        "properties": {
          "host_follower_count": {
            "description": "The host's follower count at fetch time; null when hidden.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "host_sec_uid": {
            "description": "The host's secUid, TikTok's account key that survives a rename.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_age_restricted": {
            "description": "Viewers must be of age to watch the room; null when the source does not show it.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_subscriber_only": {
            "description": "Only the host's paying subscribers can watch.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "stream_id": {
            "description": "TikTok's ID of the room's current stream (in its playback links).",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "host_sec_uid",
          "host_follower_count",
          "stream_id",
          "is_subscriber_only",
          "is_age_restricted"
        ],
        "type": "object"
      },
      "TikTokMatchedSong": {
        "properties": {
          "id": {
            "description": "TikTok's ID of the song (not a sound ID: a sound endpoint does not take it). An official clip of a song and the original sounds matched to it share it, so grouping on it counts every use of the song; null when not stated.",
            "type": [
              "string",
              "null"
            ]
          },
          "streaming_links": {
            "description": "The matched song on music streaming services, as TikTok links it; [] when none.",
            "items": {
              "$ref": "#/components/schemas/StreamingLink"
            },
            "type": "array"
          }
        },
        "required": [
          "id",
          "streaming_links"
        ],
        "type": "object"
      },
      "TikTokPlaceSpecific": {
        "properties": {
          "category_path": {
            "description": "TikTok's category from broadest to most specific (Food and Drink, Fast Food, Pizza Fast Food), repeats dropped; category is the last. [] when TikTok shows none (listed in unknown_fields when the source cannot see it).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "highlights": {
            "description": "The highlight tags TikTok shows from reviews (Excellent service, Pleasant atmosphere); [] when none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "is_claimed": {
            "description": "True when a business has claimed the place on TikTok, false when none has; null when unknown.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "parent_id": {
            "description": "ID of the place TikTok files this one under (the city of a venue); a TikTok place ID. Null for a top-level place or when unknown.",
            "type": [
              "string",
              "null"
            ]
          },
          "parent_name": {
            "description": "Name of the place in parent_id.",
            "type": [
              "string",
              "null"
            ]
          },
          "rating": {
            "description": "Average TikTok review score out of 5 (metrics.review_count reviews behind it); null when the place is unrated.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "category_path",
          "parent_id",
          "parent_name",
          "rating",
          "is_claimed",
          "highlights"
        ],
        "type": "object"
      },
      "TikTokPostBoard": {
        "properties": {
          "engagement_rate": {
            "description": "Interactions per view over the post's life, as a fraction.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "organic_view_count": {
            "description": "Organic views over the post's life.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "period_end_at": {
            "description": "End of the board's window (Creative Center's latest published day).",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "period_engagement_rate": {
            "description": "Interactions per view in the board's window, as a fraction.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "period_organic_view_count": {
            "description": "Organic (unpaid) views in the board's window.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "period_six_second_view_rate": {
            "description": "Share of the window's views that lasted six seconds or more.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "period_view_count": {
            "description": "Views in the board's window, paid and organic.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "rank": {
            "description": "Position on the requested board (1 = top).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "six_second_view_rate": {
            "description": "Share of all the post's views that lasted six seconds or more.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "rank",
          "period_end_at",
          "period_view_count",
          "period_organic_view_count",
          "organic_view_count",
          "period_engagement_rate",
          "engagement_rate",
          "period_six_second_view_rate",
          "six_second_view_rate"
        ],
        "type": "object"
      },
      "TikTokPostLocation": {
        "properties": {
          "address": {
            "description": "Address line.",
            "type": [
              "string",
              "null"
            ]
          },
          "category": {
            "description": "Top-level place category.",
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "description": "City.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Place ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "Place name.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "address",
          "city",
          "category"
        ],
        "type": "object"
      },
      "TikTokPostMusic": {
        "properties": {
          "author_name": {
            "description": "Who TikTok credits for the sound.",
            "type": [
              "string",
              "null"
            ]
          },
          "cover_url": {
            "description": "Sound cover image URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "duration_ms": {
            "description": "Sound length in milliseconds.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "id": {
            "description": "Sound ID (equals the sound's id).",
            "type": [
              "string",
              "null"
            ]
          },
          "is_original": {
            "description": "An original sound a creator uploaded (false: a catalogue track).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "play_url": {
            "description": "Audio file URL, signed and expiring.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "Sound title.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "author_name",
          "is_original",
          "duration_ms",
          "cover_url",
          "play_url"
        ],
        "type": "object"
      },
      "TikTokPostSpecific": {
        "properties": {
          "author_follower_count": {
            "description": "The author's exact follower count; null when the source does not state it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "author_sec_uid": {
            "description": "The author's secUid, TikTok's account key that survives a rename.",
            "type": [
              "string",
              "null"
            ]
          },
          "board": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokPostBoard"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post on Creative Center's top videos board (tiktok.top_posts); null off a board."
          },
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country TikTok registers the post to (not the viewer's).",
            "type": [
              "string",
              "null"
            ]
          },
          "is_ad": {
            "description": "The post runs as a TikTok ad.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_ai_generated": {
            "description": "TikTok labels the post AI-generated.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "location": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokPostLocation"
              },
              {
                "type": "null"
              }
            ],
            "description": "The tagged place; null when none."
          },
          "music": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokPostMusic"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post's sound."
          }
        },
        "required": [
          "author_sec_uid",
          "country_code",
          "is_ad",
          "is_ai_generated",
          "location",
          "music",
          "author_follower_count",
          "board"
        ],
        "type": "object"
      },
      "TikTokProfileSpecific": {
        "properties": {
          "display_name_changed_at": {
            "description": "When the display name last changed, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "friend_count": {
            "description": "Mutual follows: accounts it follows that follow it back.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_business_account": {
            "description": "A TikTok business account (category names its business).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_shop_seller": {
            "description": "Sells on TikTok Shop.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "language": {
            "description": "The owner's app language (en, ko), not its posts'.",
            "type": [
              "string",
              "null"
            ]
          },
          "liked_post_count": {
            "description": "Posts it has liked (likes given); null when it keeps them private.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "sec_uid": {
            "description": "TikTok's account key: survives a rename, and handle params take it.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "sec_uid",
          "friend_count",
          "liked_post_count",
          "language",
          "is_business_account",
          "is_shop_seller",
          "display_name_changed_at"
        ],
        "type": "object"
      },
      "TikTokShopProductMetrics": {
        "properties": {
          "rating_distribution": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RatingDistribution"
              },
              {
                "type": "null"
              }
            ],
            "description": "Reviews per star rating; null when TikTok Shop does not show the breakdown."
          },
          "review_count": {
            "description": "Reviews behind rating.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "sold_count": {
            "description": "Units sold across every market since the product was listed, as TikTok Shop counts them; null when not shown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "stock_count": {
            "description": "Units in stock across every variant, as TikTok Shop reports them (it may cap the number it shows); null when hidden.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "sold_count",
          "review_count",
          "stock_count",
          "rating_distribution"
        ],
        "type": "object"
      },
      "TikTokShopProductSpecific": {
        "properties": {
          "brand": {
            "description": "Brand name, as TikTok Shop shows it; null when it shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "delivery_max_days": {
            "description": "Most days TikTok Shop estimates delivery takes in the product's market.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "delivery_min_days": {
            "description": "Fewest days TikTok Shop estimates delivery takes in the product's market.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/TikTokShopProductMetrics",
            "description": "Counts at fetch time; null = hidden or not exposed, 0 = zero."
          },
          "rating": {
            "description": "Average review score out of 5 (metrics.review_count reviews behind it); null when unrated.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "shop": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokShopShop"
              },
              {
                "type": "null"
              }
            ],
            "description": "The selling shop's rating and counts (seller names the shop); null when the page shows none."
          },
          "variants": {
            "description": "The purchasable variants (SKUs: a color, a size, a bundle), in TikTok Shop's order; [] for a product without variants (listed in unknown_fields when the source cannot see them).",
            "items": {
              "$ref": "#/components/schemas/ProductVariant"
            },
            "type": "array"
          }
        },
        "required": [
          "brand",
          "rating",
          "variants",
          "delivery_min_days",
          "delivery_max_days",
          "metrics",
          "shop"
        ],
        "type": "object"
      },
      "TikTokShopShop": {
        "properties": {
          "metrics": {
            "$ref": "#/components/schemas/TikTokShopShopMetrics",
            "description": "The shop's counts at fetch time; null = not shown, 0 = zero."
          },
          "rating": {
            "description": "The shop's average review score out of 5, shown to one decimal; null when the shop is unrated.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "rating",
          "metrics"
        ],
        "type": "object"
      },
      "TikTokShopShopMetrics": {
        "properties": {
          "follower_count": {
            "description": "Accounts following the shop.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "product_count": {
            "description": "Products the shop has on sale.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "review_count": {
            "description": "Reviews of the shop's products, behind its rating.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "sold_count": {
            "description": "Units the shop has sold across all its products and markets, as TikTok Shop counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "follower_count",
          "sold_count",
          "product_count",
          "review_count"
        ],
        "type": "object"
      },
      "TikTokSoundSpecific": {
        "properties": {
          "album": {
            "description": "Album of a catalogue track; null for original sounds and when not stated.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_commercial_music": {
            "description": "TikTok's own is_commerce_music flag, as served. Not a licence check: TikTok sets it on original sounds and leaves it false on many licensed catalogue tracks, so it does not say a sound is cleared for business accounts or ads.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "matched_song": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TikTokMatchedSong"
              },
              {
                "type": "null"
              }
            ],
            "description": "The catalogue song TikTok matched the sound's audio to (for a catalogue track, the track itself): the song behind an original sound. null when TikTok names none."
          }
        },
        "required": [
          "album",
          "is_commercial_music",
          "matched_song"
        ],
        "type": "object"
      },
      "TikTokSuggestionSpecific": {
        "properties": {
          "language": {
            "description": "The suggestion's language as TikTok labels it, an ISO 639-1 code (en, es); null when TikTok does not say.",
            "type": [
              "string",
              "null"
            ]
          },
          "score": {
            "description": "TikTok's predicted click-through rate for the suggestion, 0 to 1: a relative signal among one query's suggestions; null when not given.",
            "format": "double",
            "maximum": 1,
            "minimum": 0,
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "language",
          "score"
        ],
        "type": "object"
      },
      "TiktokAdResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Ad"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TiktokCommentResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Comment"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TiktokCommentsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), TikTok's comment ranking (the order its app shows).",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokDownloadResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Download"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TiktokEffectResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Effect"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TiktokEffect_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 30), TikTok's ranking of the effect's posts (the order its effect page shows).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokEngagementResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Engagement"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TiktokFollowersResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 30), newest follower first (most recently followed).",
            "items": {
              "$ref": "#/components/schemas/Profile"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokFollowingResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 30), most recently followed first.",
            "items": {
              "$ref": "#/components/schemas/Profile"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokHashtagResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Hashtag"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TiktokHashtag_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 10), TikTok's ranking of the hashtag's top posts (the order its embed shows).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokLiked_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 30), most recent like first (when the account liked each post).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokLiveResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Live"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TiktokPlace_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 30), TikTok's ranking of the place's posts (the order its place page shows).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokPlaylist_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 30), the playlist's own order (its owner's for a playlist, the order TikTok shows a collection's posts in).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokPlaylistsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 30), the account's playlists in the order it set, then its public collections.",
            "items": {
              "$ref": "#/components/schemas/Playlist"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokPostResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TiktokPostsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 15), newest first.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TiktokRepliesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), TikTok's reply order (the order its app shows: a reply to a reply follows the one it answers).",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokSearch_adsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 12), last shown, newest first with sort=newest, last shown, oldest first with sort=oldest, most unique users first with sort=popular, relevance (keywords) or newest with sort=relevance.",
            "items": {
              "$ref": "#/components/schemas/Ad"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokSearch_hashtagsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokSearch_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 30), TikTok's relevance order for the keyword.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokSearch_profilesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokSearch_soundsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokSearch_suggestionsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 20), TikTok's search box order (most likely search first).",
            "items": {
              "$ref": "#/components/schemas/Suggestion"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokSearch_topResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokSoundResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Sound"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TiktokSound_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 30), TikTok's ranking of the sound's posts (the order its sound page shows).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokTop_adsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 20), Creative Center's rank by rank_by, best first.",
            "items": {
              "$ref": "#/components/schemas/Ad"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokTop_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 20), Creative Center's rank by the rank_by metric (1 = top).",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokTranscriptResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Transcript"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TiktokTrending_hashtagsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 20), Creative Center's trend rank (1 = most popular).",
            "items": {
              "$ref": "#/components/schemas/Hashtag"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokTrending_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 30), TikTok's explore feed order.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokshopProductResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Product"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TiktokshopProductsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 20), TikTok Shop's store order: best-selling first (units sold, most first).",
            "items": {
              "$ref": "#/components/schemas/Product"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokshopReviewsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 5), TikTok Shop's recommended order (the order its product page shows reviews in).",
            "items": {
              "$ref": "#/components/schemas/Review"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TiktokshopSearch_productsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 30), TikTok Shop's relevance order.",
            "items": {
              "$ref": "#/components/schemas/Product"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "Topic": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform or parsed from display text (\"189M reels\": platform_specific.instagram.post_count). [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "description": {
            "description": "The platform's summary of the topic, as plain text with paragraph breaks (on Instagram, superscript markers ¹, ² cite platform_specific.instagram.source_urls by position). Null when the page has none.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native topic ID; on platforms whose topic pages are keyed by their words (Instagram), the words lowercased and joined by hyphens (harry-potter).",
            "type": "string"
          },
          "name": {
            "description": "The topic's title as its page shows it (Harry Potter); null when the source does not show it.",
            "type": [
              "string",
              "null"
            ]
          },
          "platform": {
            "description": "Platform ID (instagram, tiktok, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/TopicPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "related_searches": {
            "description": "Related searches the platform suggests for the topic, in its order; each is a topic of its own (pass it as url). [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Canonical topic page URL.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "name",
          "url",
          "description",
          "related_searches",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "TopicPlatformSpecific": {
        "properties": {
          "instagram": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InstagramTopicSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "An Instagram topic's own fields."
          },
          "pinterest": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PinterestTopicSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Pinterest topic's own fields."
          }
        },
        "type": "object"
      },
      "Transcript": {
        "properties": {
          "available_languages": {
            "description": "BCP-47 caption languages the platform offers for this post; [] if none or not listed.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "duration_ms": {
            "description": "Media duration in milliseconds; null when unknown.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "id": {
            "description": "Platform-native ID of the post (equals post.id); of an ad library entry, its library ID (equals ad.id).",
            "type": "string"
          },
          "is_auto_generated": {
            "description": "True when the track was machine-generated (platform auto-captions or ASR).",
            "type": "boolean"
          },
          "language": {
            "description": "BCP-47 language of the returned transcript; null when unknown.",
            "examples": [
              "en"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "platform": {
            "description": "Platform the media is hosted on.",
            "examples": [
              "youtube"
            ],
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/TranscriptPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "segments": {
            "description": "Timed cues in order; never empty on success.",
            "items": {
              "$ref": "#/components/schemas/Segment"
            },
            "type": "array"
          },
          "source": {
            "description": "captions = platform caption track; asr = speech-to-text on the audio. New values may be added.",
            "enum": [
              "captions",
              "asr"
            ],
            "type": "string"
          },
          "text": {
            "description": "Full transcript: segment texts joined with single spaces.",
            "type": "string"
          },
          "url": {
            "description": "Canonical URL of the post (of an ad library entry, its library page).",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "url",
          "language",
          "source",
          "is_auto_generated",
          "available_languages",
          "duration_ms",
          "segments",
          "text",
          "platform_specific"
        ],
        "type": "object"
      },
      "TranscriptPlatformSpecific": {
        "properties": {
          "reddit": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RedditTranscriptSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Reddit transcript's own fields."
          },
          "rumble": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RumbleTranscriptSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Rumble transcript's own fields."
          }
        },
        "type": "object"
      },
      "Trend": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded, bucketed or capped by the platform (Google's search volume bucket, Pinterest's rounded changes). [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "categories": {
            "description": "Categories the platform files the trend under, as shown (not normalized), the main one first; [] when none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "platform": {
            "description": "Platform ID (pinterest, google, bluesky, …).",
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/TrendPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "rank": {
            "description": "Position on the requested board, 1 = top; null when the answer is not a board.",
            "format": "int64",
            "minimum": 1,
            "type": [
              "integer",
              "null"
            ]
          },
          "term": {
            "description": "The trend's words as the platform shows them, whitespace-trimmed: a search term (Pinterest, Google and Instagram, usually lowercase: pass it as query to the platform's search endpoints) or a topic's headline (Bluesky).",
            "examples": [
              "fall nails"
            ],
            "type": "string"
          },
          "thumbnail_url": {
            "description": "A picture the platform shows beside the trend (a Pin's on Pinterest, a news article's on Google, a post's on Instagram); null when none or not read. Platform CDN URLs can expire.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none (a source that cannot see them, such as a board's history); null already means unknown for every other field. [] when every list is known.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "The trend's public page on the platform: its trend page where one answers logged out (Google Trends' explore page, Instagram's page for the term, Bluesky's feed of the topic's posts), else the platform's search results for it (Pinterest).",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "term",
          "url",
          "rank",
          "categories",
          "thumbnail_url",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "TrendPlatformSpecific": {
        "properties": {
          "google": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/GoogleTrendSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Google Trends trend's own fields."
          },
          "pinterest": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PinterestTrendSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "A Pinterest Trends trend's own fields."
          }
        },
        "type": "object"
      },
      "TrendPoint": {
        "properties": {
          "end_at": {
            "description": "End of the interval, exclusive (the next interval's start_at), RFC 3339 UTC.",
            "format": "date-time",
            "type": "string"
          },
          "popularity": {
            "description": "Searches in the interval relative to the series' peak, 0 to 1 (1 = the peak), as the platform scales them.",
            "format": "double",
            "maximum": 1,
            "minimum": 0,
            "type": "number"
          },
          "start_at": {
            "description": "Start of the interval (a week on Pinterest), RFC 3339 UTC.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "start_at",
          "end_at",
          "popularity"
        ],
        "type": "object"
      },
      "TruthsocialGroup": {
        "properties": {
          "display_name": {
            "description": "The group's name.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "The group's ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "member_count": {
            "description": "Members of the group.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "slug": {
            "description": "The group's name in its URL (truthsocial.com/group/<slug>).",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The group's page.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "slug",
          "display_name",
          "url",
          "member_count"
        ],
        "type": "object"
      },
      "TruthsocialLink": {
        "properties": {
          "description": {
            "description": "The card's summary of the page.",
            "type": [
              "string",
              "null"
            ]
          },
          "image_url": {
            "description": "The card's image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "provider": {
            "description": "The site the card names (www.foxnews.com).",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The card's headline.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The linked page.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "url",
          "title",
          "description",
          "image_url",
          "provider"
        ],
        "type": "object"
      },
      "TruthsocialPoll": {
        "properties": {
          "expires_at": {
            "description": "When voting closes (or closed), RFC 3339 UTC; null when it never does.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "The poll's ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_expired": {
            "description": "Whether voting has closed.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_multiple_choice": {
            "description": "Whether a voter can pick several options.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "options": {
            "description": "The options, in the poll's order.",
            "items": {
              "$ref": "#/components/schemas/TruthsocialPollOption"
            },
            "type": "array"
          },
          "vote_count": {
            "description": "Votes cast, over all options.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "voter_count": {
            "description": "People who voted.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "expires_at",
          "is_expired",
          "is_multiple_choice",
          "vote_count",
          "voter_count",
          "options"
        ],
        "type": "object"
      },
      "TruthsocialPollOption": {
        "properties": {
          "title": {
            "description": "The option's text.",
            "type": [
              "string",
              "null"
            ]
          },
          "vote_count": {
            "description": "Votes for it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "title",
          "vote_count"
        ],
        "type": "object"
      },
      "TruthsocialPostRef": {
        "properties": {
          "author": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "Its author."
          },
          "downvote_count": {
            "description": "Its downvotes; null unless it was made in a group, the only posts that can be downvoted.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "id": {
            "description": "Its post ID.",
            "type": [
              "string",
              "null"
            ]
          },
          "metrics": {
            "$ref": "#/components/schemas/PostMetrics",
            "description": "Its own counts: likes, replies and ReTruths. Null counts when only its id is known."
          },
          "published_at": {
            "description": "When it was posted, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Its URL; null when its author is unknown.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "published_at",
          "author",
          "metrics",
          "downvote_count"
        ],
        "type": "object"
      },
      "TruthsocialPostResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TruthsocialPostSpecific": {
        "properties": {
          "downvote_count": {
            "description": "Downvotes. Only posts made in a group can be downvoted; null on any other post. A ReTruth's are its own: the reposted post's are in reblog_of.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "edited_at": {
            "description": "When the text was last edited, RFC 3339 UTC; null when it never was.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "group": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TruthsocialGroup"
              },
              {
                "type": "null"
              }
            ],
            "description": "The Truth Social group the post was made in; null when it was posted to the author's profile."
          },
          "link": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TruthsocialLink"
              },
              {
                "type": "null"
              }
            ],
            "description": "The link preview card the post shows; null when none."
          },
          "poll": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TruthsocialPoll"
              },
              {
                "type": "null"
              }
            ],
            "description": "The poll the post carries (the reposted post's, on a ReTruth); null when it has none."
          },
          "quoted_post": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TruthsocialPostRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post this one quotes; null when it quotes none. Only its id is known when Truth Social no longer shows it."
          },
          "reblog_of": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TruthsocialPostRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post this one ReTruths (reposts); null when it is not a ReTruth. A ReTruth carries the reposted post's text and media, and its own counts."
          },
          "reply_to": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TruthsocialPostRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post this one replies to; null when it is not a reply. Only its id and its author's id are known when Truth Social does not show it."
          }
        },
        "required": [
          "reblog_of",
          "quoted_post",
          "reply_to",
          "group",
          "link",
          "edited_at",
          "downvote_count",
          "poll"
        ],
        "type": "object"
      },
      "TruthsocialPostsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 20), newest first.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TruthsocialProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TruthsocialProfileSpecific": {
        "properties": {
          "is_accepting_messages": {
            "description": "True when the account takes direct messages.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_bot": {
            "description": "True when the account says it is automated.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_discoverable": {
            "description": "True when the account lets Truth Social suggest it to others; null when it has not said.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_premium": {
            "description": "True when Truth Social marks the account as premium.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "last_post_at": {
            "description": "The day of the account's latest post, as midnight UTC RFC 3339 (the platform gives only the day: listed in approximate_fields); null when it has never posted.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "is_bot",
          "last_post_at",
          "is_premium",
          "is_accepting_messages",
          "is_discoverable"
        ],
        "type": "object"
      },
      "TwitchBroadcast": {
        "properties": {
          "category": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TwitchCategory"
              },
              {
                "type": "null"
              }
            ],
            "description": "The category it was last filed under."
          },
          "id": {
            "description": "Twitch's ID of the broadcast.",
            "type": [
              "string",
              "null"
            ]
          },
          "started_at": {
            "description": "When it went on air, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The title it aired under.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "started_at",
          "category"
        ],
        "type": "object"
      },
      "TwitchCategory": {
        "properties": {
          "box_art_url": {
            "description": "The category's cover image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Twitch's ID of the category.",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "Its name (Just Chatting).",
            "type": [
              "string",
              "null"
            ]
          },
          "slug": {
            "description": "Its name in links (twitch.tv/directory/category/just-chatting).",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "box_art_url"
        ],
        "type": "object"
      },
      "TwitchChapter": {
        "properties": {
          "category": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TwitchCategory"
              },
              {
                "type": "null"
              }
            ],
            "description": "The category; null when Twitch doesn't say."
          },
          "duration_ms": {
            "description": "How long it lasts, in milliseconds; null on the last part of a broadcast still on air.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "position_ms": {
            "description": "Where in the video it starts, in milliseconds.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "title": {
            "description": "What Twitch shows for it: the category's name.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "title",
          "position_ms",
          "duration_ms",
          "category"
        ],
        "type": "object"
      },
      "TwitchLiveSpecific": {
        "properties": {
          "base_segment_id": {
            "description": "Twitch's ID of the recurring slot, the same every week; id names this week's occurrence.",
            "type": [
              "string",
              "null"
            ]
          },
          "cancellation_ends_at": {
            "description": "When the cancellation of this slot lapses, RFC 3339 UTC; null when it is not cancelled.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "categories": {
            "description": "What the slot is filed under, whose first name is category; [] when the channel set none.",
            "items": {
              "$ref": "#/components/schemas/TwitchCategory"
            },
            "type": "array"
          },
          "is_cancelled": {
            "description": "True when the channel cancelled this slot. Twitch still lists it, and its status stays scheduled.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "repeat_ends_after_count": {
            "description": "How many times the slot airs before it stops repeating: 1 is a one-off. 0 or null: the channel set no end, and it repeats every week.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "scheduled_end_at": {
            "description": "When the scheduled broadcast is due to end, RFC 3339 UTC; null when the channel set no end.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "vacation": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TwitchScheduleBreak"
              },
              {
                "type": "null"
              }
            ],
            "description": "The channel's latest break from its schedule, as Twitch keeps it: it can be long over. Null when it has none."
          }
        },
        "required": [
          "scheduled_end_at",
          "is_cancelled",
          "cancellation_ends_at",
          "base_segment_id",
          "categories",
          "repeat_ends_after_count",
          "vacation"
        ],
        "type": "object"
      },
      "TwitchPostSpecific": {
        "properties": {
          "animated_preview_url": {
            "description": "An image holding frames of the video one above the other, which Twitch's site animates as its preview; null on a clip and while the video is still recording. On an old video the file itself can be gone.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "author_follower_count": {
            "description": "The channel's followers at fetch time, when the answer has them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "broadcast_id": {
            "description": "Twitch's ID of the broadcast the clip was cut from; null on a video.",
            "type": [
              "string",
              "null"
            ]
          },
          "broadcast_type": {
            "description": "What Twitch calls this kind of video: archive (a past broadcast), highlight, upload, premiere_upload, past_premiere or clip.",
            "type": [
              "string",
              "null"
            ]
          },
          "category": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TwitchCategory"
              },
              {
                "type": "null"
              }
            ],
            "description": "What it is filed under; null when nothing was set."
          },
          "chapters": {
            "description": "The parts of a video by category, in order, as Twitch marks them; [] when it marks none and on a clip, and listed in unknown_fields where the answer doesn't have them.",
            "items": {
              "$ref": "#/components/schemas/TwitchChapter"
            },
            "type": "array"
          },
          "clip_id": {
            "description": "Twitch's number for a clip. Its links take the slug, which is id; null on a video.",
            "type": [
              "string",
              "null"
            ]
          },
          "clipped_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The account that made the clip; author is the channel it was clipped from. Null on a video, and when Twitch no longer names the account."
          },
          "content_labels": {
            "description": "Twitch's content classification labels, its own IDs in its order (MatureGame, Gambling, DebatedSocialIssuesAndPolitics): is_nsfw is true on any of them but politics. [] when it has none, and listed in unknown_fields where the answer doesn't have them.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "deletes_at": {
            "description": "When Twitch will delete the video: past broadcasts expire, RFC 3339 UTC. Null when none is set (highlights and uploads stay) and on a clip.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "embed_url": {
            "description": "The clip's embeddable player; null on a video.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "is_featured": {
            "description": "True when the channel features the clip; null on a video.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_recording": {
            "description": "True for a past broadcast that is still being recorded because the stream is on air; null on a clip.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_restricted": {
            "description": "True when Twitch keeps the video from logged-out viewers, usually for the channel's subscribers: its fields are still answered and media[].url is null. Null on a clip, and where the answer doesn't carry what says so (the video's page, when Twitch's API is down).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "renditions": {
            "description": "The clip's files, one per quality, best first; media[0] is the first. [] on a video, and listed in unknown_fields where a source doesn't see them.",
            "items": {
              "$ref": "#/components/schemas/TwitchRendition"
            },
            "type": "array"
          },
          "source_video": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TwitchSourceVideo"
              },
              {
                "type": "null"
              }
            ],
            "description": "The past broadcast the clip was cut from; null on a video, and when Twitch no longer keeps it."
          },
          "vertical_renditions": {
            "description": "The files of the clip's vertical version, where it has one, best first; [] when it has none and on a video, and listed in unknown_fields where a source doesn't see them.",
            "items": {
              "$ref": "#/components/schemas/TwitchRendition"
            },
            "type": "array"
          }
        },
        "required": [
          "broadcast_type",
          "category",
          "is_recording",
          "is_restricted",
          "content_labels",
          "deletes_at",
          "animated_preview_url",
          "chapters",
          "clip_id",
          "embed_url",
          "is_featured",
          "clipped_by",
          "broadcast_id",
          "source_video",
          "author_follower_count",
          "renditions",
          "vertical_renditions"
        ],
        "type": "object"
      },
      "TwitchProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile",
            "description": "In Twitch's words: `is_verified` is Partner badge, `metrics.post_count` is videos."
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TwitchProfileSpecific": {
        "properties": {
          "category": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TwitchCategory"
              },
              {
                "type": "null"
              }
            ],
            "description": "The category the channel has set, whose name is category."
          },
          "channel_title": {
            "description": "The title the channel has set for its stream, which stays while it is off air.",
            "type": [
              "string",
              "null"
            ]
          },
          "concurrent_viewer_count": {
            "description": "People watching now; null when off air.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_affiliate": {
            "description": "True for a Twitch Affiliate, the program below Partner. Partners are is_verified: the badge Twitch draws is theirs.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_live": {
            "description": "True while the channel is on air, false when it is not.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_mature": {
            "description": "True when the channel marks itself as for mature audiences.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "language": {
            "description": "The broadcast language the channel has set, lowercase (en).",
            "type": [
              "string",
              "null"
            ]
          },
          "last_broadcast": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TwitchBroadcast"
              },
              {
                "type": "null"
              }
            ],
            "description": "The channel's latest broadcast, on air or over; null when it has never streamed."
          },
          "offline_image_url": {
            "description": "The image the player shows while the channel is off air.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "primary_color_hex": {
            "description": "The channel's accent color as hex digits without the #.",
            "type": [
              "string",
              "null"
            ]
          },
          "stream": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TwitchStream"
              },
              {
                "type": "null"
              }
            ],
            "description": "The broadcast on air now; null when off air."
          },
          "team": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TwitchTeam"
              },
              {
                "type": "null"
              }
            ],
            "description": "The Twitch team the channel lists first; null when it lists none."
          }
        },
        "required": [
          "is_live",
          "concurrent_viewer_count",
          "is_affiliate",
          "stream",
          "last_broadcast",
          "channel_title",
          "category",
          "language",
          "is_mature",
          "primary_color_hex",
          "offline_image_url",
          "team"
        ],
        "type": "object"
      },
      "TwitchRendition": {
        "properties": {
          "expires_at": {
            "description": "When url stops working, RFC 3339 UTC, read from Twitch's signed token; null when unknown.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "frame_rate": {
            "description": "Frames per second, when Twitch states it.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "quality": {
            "description": "Twitch's name for the quality: the height in pixels (1080).",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The MP4 file, signed and expiring: see expires_at.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "quality",
          "frame_rate",
          "url",
          "expires_at"
        ],
        "type": "object"
      },
      "TwitchScheduleBreak": {
        "properties": {
          "end_at": {
            "description": "When the break ends, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "reason": {
            "description": "Twitch's word for the break, lowercase (vacation).",
            "type": [
              "string",
              "null"
            ]
          },
          "start_at": {
            "description": "When the break starts, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "start_at",
          "end_at",
          "reason"
        ],
        "type": "object"
      },
      "TwitchScheduleResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), Soonest first, a week per page.",
            "items": {
              "$ref": "#/components/schemas/Live"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "TwitchSourceVideo": {
        "properties": {
          "id": {
            "description": "The video's number.",
            "type": [
              "string",
              "null"
            ]
          },
          "offset_ms": {
            "description": "Where in the video the clip starts, in milliseconds; null when Twitch doesn't say.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "title": {
            "description": "The video's title.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The video's page.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "offset_ms"
        ],
        "type": "object"
      },
      "TwitchStream": {
        "properties": {
          "category": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TwitchCategory"
              },
              {
                "type": "null"
              }
            ],
            "description": "The category it is filed under."
          },
          "id": {
            "description": "Twitch's ID of the broadcast, which last_broadcast.id and a clip's broadcast_id also write.",
            "type": [
              "string",
              "null"
            ]
          },
          "started_at": {
            "description": "When it went on air, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "tags": {
            "description": "The tags the channel set, as shown; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "thumbnail_url": {
            "description": "A preview frame of the broadcast, renewed while it airs.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "The broadcast's title.",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "Twitch's word for what is on air (live).",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "type",
          "started_at",
          "tags",
          "category",
          "thumbnail_url"
        ],
        "type": "object"
      },
      "TwitchTeam": {
        "properties": {
          "display_name": {
            "description": "Its name as shown.",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Twitch's ID of the team.",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "Its name in links.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "display_name"
        ],
        "type": "object"
      },
      "TwitchTranscriptResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Transcript"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TwitchVideoResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "TwitchVideosResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 100), newest first with sort=newest, Twitch's most viewed first, of all time with sort=popular.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "Username": {
        "properties": {
          "id": {
            "description": "The username checked, as its identifier: the same value as username (a name, free or taken, has no other ID in a sign-up check).",
            "examples": [
              "socialtap"
            ],
            "type": "string"
          },
          "is_available": {
            "description": "True when the platform would let someone register the username now; false when it is taken, reserved or breaks the platform's username rules (reason and message say which); null when the platform did not say.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "message": {
            "description": "The platform's own explanation when the username is not available, as its sign-up form shows it (English); null when it is available.",
            "type": [
              "string",
              "null"
            ]
          },
          "platform": {
            "description": "Platform whose sign-up checked the username.",
            "examples": [
              "instagram"
            ],
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/UsernamePlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "reason": {
            "description": "Why the username is not available: taken = registered to an account or reserved by the platform (platforms don't tell the two apart); invalid = breaks the platform's username rules (length, characters). Null when it is available or the platform gave no reason. New values may be added.",
            "enum": [
              "taken",
              "invalid",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "suggestions": {
            "description": "Free usernames the platform's sign-up form proposes for this one, in its order; [] when it proposes none (platforms suggest nothing for short, protected or brand names). Free when proposed: someone can take one at any time.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "The profile page at this username: the account's page when it is taken, the page it would have once registered (until then the platform answers it as not found); null when that address is one of the platform's own pages (instagram.com/explore/), not an account's.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "username": {
            "description": "The username checked, without @, in the platform's canonical form (lowercase where usernames are case-insensitive).",
            "examples": [
              "socialtap"
            ],
            "type": "string"
          }
        },
        "required": [
          "platform",
          "id",
          "username",
          "url",
          "is_available",
          "reason",
          "message",
          "suggestions",
          "platform_specific"
        ],
        "type": "object"
      },
      "UsernamePlatformSpecific": {
        "type": "object"
      },
      "Warning": {
        "properties": {
          "code": {
            "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
            "type": "string"
          },
          "doc_url": {
            "description": "Where to read more (the changelog entry, the endpoint's docs).",
            "type": "string"
          },
          "fields": {
            "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "message": {
            "description": "What to do about it.",
            "type": "string"
          }
        },
        "required": [
          "code",
          "message",
          "doc_url"
        ],
        "type": "object"
      },
      "WebPage": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values rounded by the platform (Facebook's \"57K\": metrics.share_count). [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "metrics": {
            "$ref": "#/components/schemas/WebPageMetrics",
            "description": "Counts at fetch time; null = the platform did not say, 0 = it counts none."
          },
          "platform": {
            "description": "Platform that counted the page's link.",
            "examples": [
              "pinterest"
            ],
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/WebPagePlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none; a web page has no lists, so always [].",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "The web page's link, exactly as sent (not normalized): platforms that count the exact string (Pinterest) count https://example.com and https://example.com/ apart.",
            "examples": [
              "https://www.allrecipes.com/recipe/10813/best-chocolate-chip-cookies/"
            ],
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "url",
          "metrics",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "WebPageMetrics": {
        "properties": {
          "share_count": {
            "description": "How many times the platform's users shared this link to it, as its own share or save button counts them (Pinterest: saves, each a Pin of the page). 0 when none did, which is also the answer for a page that doesn't exist: platforms count links without opening them. Rounded where the platform shows it rounded (Facebook; see approximate_fields). Null when the platform gave no count.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "share_count"
        ],
        "type": "object"
      },
      "WebPagePlatformSpecific": {
        "type": "object"
      },
      "WebResult": {
        "properties": {
          "approximate_fields": {
            "description": "JSON paths of values parsed from the index's display text or rounded there (profile.metrics.follower_count from \"13K followers\", a profile.bio or post.text the snippet cut short). Filled values are exact and leave the list. [] when all exact.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "community": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CommunitySummary"
              },
              {
                "type": "null"
              }
            ],
            "description": "The community the result names (type community: a group, a subreddit): what its link and the index's text say of it, completed from details when the result is filled. Null for every other type."
          },
          "details": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/WebResultDetails"
              },
              {
                "type": "null"
              }
            ],
            "description": "The item's own record from the platform, fetched when the request asked for it (fill=true): what the platform's endpoint for the kind returns, under the result's type (details.profile). Null when not asked for, when the platform has no endpoint for the kind, or when it did not serve the item (meta.warnings says how many)."
          },
          "hashtag": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/HashtagSummary"
              },
              {
                "type": "null"
              }
            ],
            "description": "The hashtag the result names (type hashtag): what its link and the index's text say of it, completed from details when the result is filled. Null for every other type."
          },
          "matched_url": {
            "description": "The page the index listed: the item's own page, or one of its pages that names it (a video of an account, for a profile found through it).",
            "format": "uri",
            "type": "string"
          },
          "place": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PlaceSummary"
              },
              {
                "type": "null"
              }
            ],
            "description": "The place the result names (type place): what its link and the index's text say of it, completed from details when the result is filled. Null for every other type."
          },
          "platform": {
            "description": "Platform the item is on.",
            "examples": [
              "instagram"
            ],
            "type": "string"
          },
          "platform_specific": {
            "$ref": "#/components/schemas/WebResultPlatformSpecific",
            "description": "Fields only this platform has, under its ID (platform_specific.<platform>); each null when unknown."
          },
          "position": {
            "description": "Zero-based rank of the result in the list, across pages: the search engine's order, counting only the results kept.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "post": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PostSummary"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post the result names (type post): what its link and the index's text say of it, completed from details when the result is filled. Null for every other type."
          },
          "profile": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileSummary"
              },
              {
                "type": "null"
              }
            ],
            "description": "The account the result names (type profile): what its link and the index's text say of it, completed from details when the result is filled. Null for every other type."
          },
          "snippet": {
            "description": "The index's excerpt of the page: often the item's description and counts as the page stated them when it was indexed, days or weeks ago. Null when the index shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "sound": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SoundSummary"
              },
              {
                "type": "null"
              }
            ],
            "description": "The sound the result names (type sound): what its link and the index's text say of it, completed from details when the result is filled. Null for every other type."
          },
          "title": {
            "description": "The page's title as the index shows it: often the item's name, but not the item's own field. Null when the index shows none.",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "The kind of item the result names, as the resource that describes it: profile (an account), post, hashtag, sound, place or community. The item's summary is the field of that name, and a filled result's record is details.<type>. A search that finds several kinds (a platform's top search) mixes them in one list. New values may be added as more kinds are searchable; treat unknown values as other.",
            "enum": [
              "profile",
              "post",
              "hashtag",
              "sound",
              "place",
              "community"
            ],
            "type": "string"
          },
          "unknown_fields": {
            "description": "JSON paths of lists whose [] means unknown rather than none; [] when every list is known (a result has none yet).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "The item's canonical link on the platform (the account's page for a profile, the post's for a post).",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "platform",
          "type",
          "position",
          "url",
          "matched_url",
          "title",
          "snippet",
          "profile",
          "post",
          "hashtag",
          "sound",
          "place",
          "community",
          "details",
          "platform_specific",
          "approximate_fields",
          "unknown_fields"
        ],
        "type": "object"
      },
      "WebResultDetails": {
        "properties": {
          "community": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Community"
              },
              {
                "type": "null"
              }
            ],
            "description": "The community's full record (type community), as the platform's endpoint for it returns it now; null for every other type."
          },
          "hashtag": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Hashtag"
              },
              {
                "type": "null"
              }
            ],
            "description": "The hashtag's full record (type hashtag), as the platform's hashtag endpoint returns it now; null for every other type."
          },
          "place": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Place"
              },
              {
                "type": "null"
              }
            ],
            "description": "The place's full record (type place), as the platform's place endpoint returns it now; null for every other type."
          },
          "post": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Post"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post's full record (type post), as the platform's post endpoint returns it now; null for every other type."
          },
          "profile": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Profile"
              },
              {
                "type": "null"
              }
            ],
            "description": "The account's full record (type profile), as the platform's profile endpoint returns it now; null for every other type."
          },
          "sound": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Sound"
              },
              {
                "type": "null"
              }
            ],
            "description": "The sound's full record (type sound), as the platform's sound endpoint returns it now; null for every other type."
          }
        },
        "required": [
          "profile",
          "post",
          "hashtag",
          "sound",
          "place",
          "community"
        ],
        "type": "object"
      },
      "WebResultPlatformSpecific": {
        "properties": {
          "facebook": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FacebookWebResultSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "What the index shows of a Facebook account beyond the summary."
          },
          "linkedin": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LinkedInWebResultSpecific"
              },
              {
                "type": "null"
              }
            ],
            "description": "What the index shows of a LinkedIn account beyond the summary."
          }
        },
        "type": "object"
      },
      "XAffiliation": {
        "properties": {
          "badge_url": {
            "description": "The badge image (the organization's avatar).",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "The organization's name, as the badge's label shows it.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The organization's X profile URL, when the badge links to one.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "url",
          "badge_url"
        ],
        "type": "object"
      },
      "XArticle": {
        "properties": {
          "cover_image_url": {
            "description": "Its cover image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "The article's own ID (x.com/i/article/<id>), not the post's.",
            "type": [
              "string",
              "null"
            ]
          },
          "modified_at": {
            "description": "When it was last changed, RFC 3339 UTC; null when the source does not show it.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "preview_text": {
            "description": "The short preview X shows of the body.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "preview_text",
          "cover_image_url",
          "modified_at"
        ],
        "type": "object"
      },
      "XCard": {
        "properties": {
          "description": {
            "description": "Its description.",
            "type": [
              "string",
              "null"
            ]
          },
          "domain": {
            "description": "The domain of the linked page.",
            "type": [
              "string",
              "null"
            ]
          },
          "image_url": {
            "description": "Its largest image.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "Its headline.",
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "description": "X's name for the card (summary, summary_large_image, player, broadcast, …). New values may be added.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Where the card leads, when X says.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "type",
          "url",
          "title",
          "description",
          "domain",
          "image_url"
        ],
        "type": "object"
      },
      "XCommunityResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Community"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "XCommunitySpecific": {
        "properties": {
          "creator": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The account that created it (it may have passed to another admin since)."
          },
          "invite_policy": {
            "description": "Who can invite people in: members, moderators, admins or none. New values may be added.",
            "enum": [
              "members",
              "moderators",
              "admins",
              "none",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "join_policy": {
            "description": "How people join: open (anyone), moderator_approval or admin_approval (a request someone approves), invite_only (by invitation). New values may be added.",
            "enum": [
              "open",
              "moderator_approval",
              "admin_approval",
              "invite_only",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "join_question": {
            "description": "The question X asks people who ask to join, as its moderators wrote it; null when it asks none.",
            "type": [
              "string",
              "null"
            ]
          },
          "moderator_count": {
            "description": "People who run it, its admin included, as X counts them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "sample_members": {
            "description": "The few members X shows on the community's page: a sample chosen by X, not its member list.",
            "items": {
              "$ref": "#/components/schemas/ProfileRef"
            },
            "type": "array"
          },
          "search_tags": {
            "description": "Words its moderators chose for people to find it by; [] when none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "join_policy",
          "join_question",
          "invite_policy",
          "creator",
          "moderator_count",
          "search_tags",
          "sample_members"
        ],
        "type": "object"
      },
      "XEmbeddedPost": {
        "properties": {
          "author": {
            "$ref": "#/components/schemas/ProfileRef",
            "description": "Its author."
          },
          "id": {
            "description": "Its ID, as x.post takes it.",
            "type": [
              "string",
              "null"
            ]
          },
          "media": {
            "description": "Its attachments; [] for a text post.",
            "items": {
              "$ref": "#/components/schemas/Media"
            },
            "type": "array"
          },
          "metrics": {
            "$ref": "#/components/schemas/PostMetrics",
            "description": "Its counts at fetch time."
          },
          "published_at": {
            "description": "When it was posted, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "text": {
            "description": "Its text, with the links written out.",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "Its URL.",
            "format": "uri",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "text",
          "published_at",
          "author",
          "media",
          "metrics"
        ],
        "type": "object"
      },
      "XMediaVariant": {
        "properties": {
          "bitrate": {
            "description": "Bits per second; null for a playlist, which holds several.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "content_type": {
            "description": "Its type (video/mp4, application/x-mpegURL).",
            "type": [
              "string",
              "null"
            ]
          },
          "media_index": {
            "description": "Which item of media this is a rendition of, from 0.",
            "format": "int64",
            "type": "integer"
          },
          "url": {
            "description": "The file or playlist.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "media_index",
          "url",
          "content_type",
          "bitrate"
        ],
        "type": "object"
      },
      "XPoll": {
        "properties": {
          "choices": {
            "description": "The choices, in the post's order.",
            "items": {
              "$ref": "#/components/schemas/XPollChoice"
            },
            "type": "array"
          },
          "duration_minutes": {
            "description": "How long voting runs, in minutes.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "ends_at": {
            "description": "When voting ends or ended, RFC 3339 UTC.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "is_final": {
            "description": "True when voting is over and the counts are final.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "total_votes": {
            "description": "Votes across every choice; null when a choice's count is hidden.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "choices",
          "total_votes",
          "ends_at",
          "duration_minutes",
          "is_final"
        ],
        "type": "object"
      },
      "XPollChoice": {
        "properties": {
          "label": {
            "description": "The choice's text.",
            "type": [
              "string",
              "null"
            ]
          },
          "vote_count": {
            "description": "Exact votes for it; null when X does not show them.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "label",
          "vote_count"
        ],
        "type": "object"
      },
      "XPostCommunity": {
        "properties": {
          "id": {
            "description": "The community's ID, as x.com/i/communities/<id> shows it.",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "Its name; null when the source does not show it.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name"
        ],
        "type": "object"
      },
      "XPostResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "XPostSpecific": {
        "properties": {
          "article": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/XArticle"
              },
              {
                "type": "null"
              }
            ],
            "description": "The X Article this post publishes (its title is in title, its body in text); null when it is an ordinary post."
          },
          "author_metrics": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileMetrics"
              },
              {
                "type": "null"
              }
            ],
            "description": "The author's counts at fetch time (followers, following, posts), which X answers with the post; null when the source does not show them. x.profile has the rest of the account."
          },
          "author_verified_type": {
            "description": "The kind of verified organization X says the author is (business: the gold check, government: the grey one); null when it is neither. New values may be added; treat unknown values as other.",
            "enum": [
              "business",
              "government",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "card": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/XCard"
              },
              {
                "type": "null"
              }
            ],
            "description": "The preview card the post shows for a link or a broadcast; null when it has none, or when X answers the card without its content."
          },
          "cashtags": {
            "description": "Cashtags in the text, without the $, case kept; [] if none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "community": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/XPostCommunity"
              },
              {
                "type": "null"
              }
            ],
            "description": "The community the post was posted to; null when none."
          },
          "conversation_id": {
            "description": "ID of the post that started the conversation (this post's own ID when it started one); null when the source does not show it.",
            "type": [
              "string",
              "null"
            ]
          },
          "edit_post_ids": {
            "description": "IDs of every version of this post, oldest first, the last one current; one ID when it was never edited, [] when the source does not show them.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "is_author_blue_verified": {
            "description": "True when the author has the blue check of an X Premium subscription; null when unknown. author.is_verified is true for any check.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_edited": {
            "description": "True when the post has more than one version; null when the source does not show them.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "links": {
            "description": "The links in the text, written out from X's t.co short links, each once, titled as the post shows them; [] if none.",
            "items": {
              "$ref": "#/components/schemas/Link"
            },
            "type": "array"
          },
          "media_variants": {
            "description": "Every rendition X offers of the post's videos and GIFs (MP4s by bitrate, the HLS playlist); media[].url is the best MP4. [] when the post has none.",
            "items": {
              "$ref": "#/components/schemas/XMediaVariant"
            },
            "type": "array"
          },
          "poll": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/XPoll"
              },
              {
                "type": "null"
              }
            ],
            "description": "The poll in the post, with exact vote counts; null when it has none."
          },
          "quoted_post": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/XEmbeddedPost"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post this one quotes, as X embeds it; null when it quotes none, or when the quoted post is no longer shown."
          },
          "quoted_post_id": {
            "description": "ID of the post this one quotes; null when it quotes none. Stays set when the quoted post itself is gone.",
            "type": [
              "string",
              "null"
            ]
          },
          "reply_to_author": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProfileRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The author of the post this one replies to (ID and username, when X says); null when it is not a reply."
          },
          "reply_to_post_id": {
            "description": "ID of the post this one replies to; null when it is not a reply.",
            "type": [
              "string",
              "null"
            ]
          },
          "reposted_post": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/XEmbeddedPost"
              },
              {
                "type": "null"
              }
            ],
            "description": "The post this repost shows, with its own author and counts; null when this is no repost. text, media and metrics are that post's."
          },
          "reposted_post_id": {
            "description": "ID of the post this repost shows; null when this is no repost.",
            "type": [
              "string",
              "null"
            ]
          },
          "source": {
            "description": "The client the post was sent from, as X labels it (Twitter Web Client, Twitter for iPhone, …); null when X does not say, as on most recent posts.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "author_metrics",
          "is_author_blue_verified",
          "author_verified_type",
          "conversation_id",
          "reply_to_post_id",
          "reply_to_author",
          "quoted_post_id",
          "quoted_post",
          "reposted_post_id",
          "reposted_post",
          "edit_post_ids",
          "is_edited",
          "source",
          "cashtags",
          "links",
          "media_variants",
          "poll",
          "card",
          "article",
          "community"
        ],
        "type": "object"
      },
      "XProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "XProfileSpecific": {
        "properties": {
          "affiliation": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/XAffiliation"
              },
              {
                "type": "null"
              }
            ],
            "description": "The organization X shows the account as affiliated with (its badge beside the name); null when none or when the source does not show it."
          },
          "highlighted_post_count": {
            "description": "Posts on the profile's Highlights tab; null when the source does not show it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "is_blue_verified": {
            "description": "True when the account has the blue check of an X Premium subscription, false when it does not; null when unknown. is_verified is true for any check.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_identity_verified": {
            "description": "True when X verified the owner's identity with an ID document, false when it did not; null when the source does not show it.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_possibly_sensitive": {
            "description": "True when X marks the account's media as possibly sensitive by default, false otherwise; null when unknown.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "like_count": {
            "description": "Posts the account has liked (likes given, not received); null when the source does not show it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "listed_count": {
            "description": "Public lists the account is a member of; null when the source does not show it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "media_count": {
            "description": "Posts with photos or videos, as the profile's Media tab counts them; null when the source does not show it.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "pinned_post_ids": {
            "description": "IDs of the posts pinned to the top of the profile, as x.post takes them; [] when none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "professional_type": {
            "description": "The professional account kind the owner chose (business or creator); null for a personal account or when the source does not show it. New values may be added; treat unknown values as other.",
            "enum": [
              "business",
              "creator",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "verified_at": {
            "description": "When the account's current check was granted, RFC 3339 UTC; null when it has none or the source does not show it.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "verified_type": {
            "description": "The kind of verified organization X says the account is (business: the gold check, government: the grey one); null when it is neither, or when the source does not show it. New values may be added; treat unknown values as other.",
            "enum": [
              "business",
              "government",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "withheld_in_countries": {
            "description": "ISO 3166-1 alpha-2 codes of the countries where X withholds the account for legal reasons, upper case; [] when none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "verified_type",
          "is_blue_verified",
          "is_identity_verified",
          "verified_at",
          "listed_count",
          "media_count",
          "like_count",
          "highlighted_post_count",
          "pinned_post_ids",
          "professional_type",
          "affiliation",
          "is_possibly_sensitive",
          "withheld_in_countries"
        ],
        "type": "object"
      },
      "XSearch_communitiesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "XSearch_hashtagsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "XSearch_postsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "XSearch_profilesResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 50), the search engine's ranking (most relevant first).",
            "items": {
              "$ref": "#/components/schemas/WebResult"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "YouTubeChapter": {
        "properties": {
          "start_ms": {
            "description": "Start, in ms from the beginning.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "title": {
            "description": "Chapter title.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "title",
          "start_ms"
        ],
        "type": "object"
      },
      "YouTubeHashtagSpecific": {
        "properties": {
          "channel_count": {
            "description": "Channels that posted with the tag, rounded by YouTube (in approximate_fields).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "channel_count"
        ],
        "type": "object"
      },
      "YouTubePlaylistSpecific": {
        "properties": {
          "updated_at": {
            "description": "When its owner last changed it, RFC 3339 UTC; YouTube shows only a date (listed in approximate_fields).",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "view_count": {
            "description": "Views YouTube counts for the playlist as a whole.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "view_count",
          "updated_at"
        ],
        "type": "object"
      },
      "YouTubePostSpecific": {
        "properties": {
          "author_subscriber_count": {
            "description": "The channel's subscriber count, rounded by YouTube (in approximate_fields); null when hidden.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "category": {
            "description": "YouTube category (Music, Gaming, …), in English.",
            "type": [
              "string",
              "null"
            ]
          },
          "chapters": {
            "description": "Chapters in playback order; [] when none.",
            "items": {
              "$ref": "#/components/schemas/YouTubeChapter"
            },
            "type": "array"
          },
          "description_links": {
            "description": "Links in the description, in order, deduplicated; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "is_age_restricted": {
            "description": "Viewers must sign in to confirm their age; null when the answer does not tell.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_live_now": {
            "description": "A live stream on air now.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_paywalled": {
            "description": "Must be bought or rented (movies, paid content).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_unlisted": {
            "description": "Unlisted: watchable by link, not listed on the channel or in search.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "keywords": {
            "description": "The uploader's tags; [] when none.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "live_ended_at": {
            "description": "When a live stream or premiere ended; null while live or if never live.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "live_started_at": {
            "description": "When a live stream or premiere went on air; null if never live.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "scheduled_start_at": {
            "description": "When a scheduled stream or premiere is due to start; null otherwise.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "category",
          "keywords",
          "chapters",
          "description_links",
          "is_unlisted",
          "is_age_restricted",
          "is_paywalled",
          "is_live_now",
          "live_started_at",
          "live_ended_at",
          "scheduled_start_at",
          "author_subscriber_count"
        ],
        "type": "object"
      },
      "YouTubeProfileSpecific": {
        "properties": {
          "is_business_email_listed": {
            "description": "True when the channel lists a business email (shown to signed-in users only; the address is not returned); null otherwise, since YouTube shows nothing for a channel without one.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_official_artist_channel": {
            "description": "True for an Official Artist Channel (the note badge after its name), false for any other channel; null when the page shows no badge row (YouTube's built-in channels).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_subscriber_count_hidden": {
            "description": "True when the channel hides its subscriber count (metrics.follower_count is then null; neither its About panel nor its header shows one), false when YouTube shows it; null when that cannot be told (no About panel or header seen).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "keywords": {
            "description": "The channel's keywords as its owner wrote them, a quoted phrase as one keyword; [] when it has none (listed in unknown_fields when the source cannot see them).",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "keywords",
          "is_official_artist_channel",
          "is_subscriber_count_hidden",
          "is_business_email_listed"
        ],
        "type": "object"
      },
      "YoutubeCommentsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 20), newest first with sort=newest, YouTube's Top comments ranking with sort=popular.",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "YoutubeEngagementResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Engagement"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "YoutubePostResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Post"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "YoutubePostsResponse": {
        "properties": {
          "data": {
            "description": "Up to limit items (page size 48), newest first with sort=newest, oldest first with sort=oldest, YouTube's Popular order (most viewed first) with sort=popular.",
            "items": {
              "$ref": "#/components/schemas/Post"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "page": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "data",
          "page",
          "meta"
        ],
        "type": "object"
      },
      "YoutubeProfileResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Profile"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      },
      "YoutubeTranscriptResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Transcript"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "apiKey": {
        "in": "header",
        "name": "x-api-key",
        "type": "apiKey"
      },
      "session": {
        "description": "The dashboard session (https://socialtap.dev/dashboard/): a person signed in, acting on one of their accounts (x-account-id; default: their own) with their role in it. Browsers send it; API clients use the API key.",
        "in": "cookie",
        "name": "__Host-st_session",
        "type": "apiKey"
      }
    }
  },
  "info": {
    "description": "SocialTap is the social media scraper API for developers and AI agents. Send a public link, a handle or a search and get live data back in one schema. Failed requests are free. Available now: ads on Facebook, Google, LinkedIn and TikTok; albums on Apple Music and Spotify; comments on Bluesky, Facebook, Instagram, Reddit, Rumble, Snapchat, Threads, TikTok and YouTube; communities on Facebook, Reddit and X; downloads on TikTok; effects on TikTok; embeds on Instagram; engagement stats on Facebook, Instagram, Reddit, Rumble, TikTok and YouTube; events on Facebook; hashtags on Instagram and TikTok; livestreams on TikTok and Twitch; offers on Amazon; places on Facebook and Instagram; playlists on Amazon, Apple Music, Instagram, Pinterest, Spotify and TikTok; podcasts on Spotify; posts on Amazon, Apple Music, Bluesky, Facebook, Instagram, Kick, Kwai, LinkedIn, Pinterest, Reddit, Rumble, Snapchat, SoundCloud, Spotify, Telegram, Threads, TikTok, Truth Social, Twitch, X and YouTube; products on Amazon, Facebook and TikTok Shop; profiles on Amazon, Apple Music, Bluesky, Facebook, Google, Instagram, Komi, Kwai, LinkedIn, Linkme, Linktree, Lnk.Bio, Pillar, Pinterest, Reddit, Rumble, Snapchat, SoundCloud, Spotify, Telegram, Threads, TikTok, Truth Social, Twitch, X and YouTube; reviews on Amazon and TikTok Shop; sounds on Instagram and TikTok; suggestions on Google, Instagram and TikTok; topics on Instagram and Pinterest; transcripts on Facebook, Instagram, Kick, Reddit, Rumble, TikTok, Twitch and YouTube; trends on Pinterest; usernames on Instagram; web pages on Pinterest; web results on Facebook, Instagram, LinkedIn, Telegram, TikTok and X.\n\n**AI agents and coding assistants:** before writing integration code, read [llms.txt](https://socialtap.dev/llms.txt) (how to authenticate, pick an endpoint, paginate and handle errors, plus every endpoint), the [agent guide](https://socialtap.dev/docs/agents/) and the [API reference](https://socialtap.dev/docs/reference/). Every docs page is also Markdown: append `index.md` to its URL or send `Accept: text/markdown`.\n\nAuthenticate with the `x-api-key` header. Branch on `error.code`, never on `message`; retry only the codes an operation's `x-socialtap-retry` lists as retryable ([error codes](https://socialtap.dev/docs/errors/)). Plans do not limit request rate: a per-account runaway ceiling answers `rate_limited` with a `retry-after` header.\n\nEvery operation states its price in `x-socialtap-pricing` (credits per request, or per page for lists), list operations their cursor paging in `x-socialtap-pagination`.\n\nFailed requests and cache hits cost no credits.",
    "title": "SocialTap API",
    "version": "1"
  },
  "openapi": "3.1.0",
  "paths": {
    "/status.json": {
      "get": {
        "description": "Public, no API key. `status` is health from the scheduled canaries: an endpoint is degraded after repeated failed runs and healthy again after several passes; unknown until first checked, and again when the canary has not run recently. `success_rate` is the share of customer requests in the last `success_rate_window_minutes` that got an answer, measured where every request ends (failures on SocialTap's side, including capacity refusals, count against it; requests refused for credits or rate do not count), rounded down; null when there was too little traffic. Cached for 60 seconds.",
        "operationId": "status.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "endpoints": {
                      "items": {
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "last_checked": {
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "measured": {
                            "description": "Requests, success rate and latency between measured_from and measured_to; null when the endpoint had fewer than measured_min_requests requests.",
                            "properties": {
                              "check_requests": {
                                "description": "Of requests, how many were our own scheduled checks.",
                                "minimum": 0,
                                "type": "integer"
                              },
                              "p50_ms": {
                                "description": "Median time the engine took for a successful answer, ms; null when none was timed.",
                                "minimum": 0,
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "p95_ms": {
                                "description": "95th percentile of that time, ms; null when none was timed.",
                                "minimum": 0,
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "requests": {
                                "description": "Requests measured: customer requests plus scheduled checks.",
                                "minimum": 0,
                                "type": "integer"
                              },
                              "success_rate": {
                                "description": "Share of requests that succeeded (0..1, rounded down).",
                                "maximum": 1,
                                "minimum": 0,
                                "type": "number"
                              }
                            },
                            "required": [
                              "requests",
                              "check_requests",
                              "success_rate",
                              "p50_ms",
                              "p95_ms"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "since": {
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "description": "Canary health; unknown until first checked, or when the canary has not run recently.",
                            "enum": [
                              "healthy",
                              "degraded",
                              "unknown"
                            ],
                            "type": "string"
                          },
                          "success_rate": {
                            "description": "Real-traffic success rate over the window (0..1, rounded down); null when there was too little traffic.",
                            "maximum": 1,
                            "minimum": 0,
                            "type": [
                              "number",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "status",
                          "since",
                          "last_checked",
                          "success_rate",
                          "measured"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "environment": {
                      "type": "string"
                    },
                    "generated_at": {
                      "format": "date-time",
                      "type": "string"
                    },
                    "measured_from": {
                      "description": "Start of every endpoint's measured window; null until the measurement has run.",
                      "format": "date-time",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "measured_min_requests": {
                      "description": "Fewest requests an endpoint needs in the window for its measured numbers to be published.",
                      "minimum": 1,
                      "type": "integer"
                    },
                    "measured_to": {
                      "description": "End of every endpoint's measured window; null until the measurement has run.",
                      "format": "date-time",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "success_rate_window_minutes": {
                      "description": "Window of every endpoint's success_rate.",
                      "type": "integer"
                    }
                  },
                  "required": [
                    "generated_at",
                    "environment",
                    "success_rate_window_minutes",
                    "measured_from",
                    "measured_to",
                    "measured_min_requests",
                    "endpoints"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Health document"
          }
        },
        "security": [],
        "summary": "Live health of every endpoint",
        "tags": [
          "Status"
        ],
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [],
          "retry_after_header": "retry-after",
          "retryable_codes": []
        }
      }
    },
    "/v1/account": {
      "delete": {
        "description": "Locks the account at once (every key revoked, the owner's sessions ended, jobs and webhooks stopped) and deletes it for good after `grace_s` (7 days), unless its owner signs in again and chooses it; unspent credits are forfeited. Its people on other accounts stay on those. The owner only, with a fresh sign-in. Free.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "account.delete",
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "account_id": {
                          "description": "The account being deleted.",
                          "type": "string"
                        },
                        "credits_forfeited": {
                          "description": "The balance when the deletion was asked for: forfeited, with no refund, when the account is deleted.",
                          "type": "integer"
                        },
                        "deletes_at": {
                          "description": "When the account is deleted for good, unless its owner signs in before then (which cancels the deletion), RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always account_deletion.",
                          "enum": [
                            "account_deletion"
                          ],
                          "type": "string"
                        },
                        "requested_at": {
                          "description": "When its deletion was asked for, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "account_id",
                        "requested_at",
                        "deletes_at",
                        "credits_forfeited"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Delete the account (after a grace period)",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Delete the account (after a grace period)",
        "tags": [
          "Account"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "owner",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "get": {
        "description": "The account's balance and plan, the low-balance alert threshold, and the calling key: its scopes, spend limit (with what it used this interval) and expiry. Free; never cached. A pending agent key may call it (and nothing else) to learn when its owner confirmed.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "account.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "api_key": {
                          "description": "The key that made this request; null for a dashboard session.",
                          "properties": {
                            "created_at": {
                              "description": "When the key was created, RFC 3339 UTC.",
                              "format": "date-time",
                              "type": "string"
                            },
                            "created_by_key": {
                              "description": "The API key (key_…) that last created this key, gave it the admin scope or rotated it: revoking that key also revokes this one if this one has admin. Null when none did, or a person has rotated it in the dashboard since.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "created_by_user": {
                              "description": "The person (GET /v1/members user_id) who created this key in the dashboard, or whose key created it. They may have left the account since. Null when no person did (an operator, or a key from before this was recorded).",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "dashboard": {
                              "description": "true for the account's built-in dashboard key: the dashboard's playground runs as it (so its requests are logged, counted and billed like any key's). Nobody holds its secret, so it works only from the signed-in dashboard. Only its spend_limit can be changed (to cap what the playground spends live); renaming, rescoping, restricting, rotating or revoking it is forbidden (details.reason dashboard_key). It is made on first use and revoked with the account.",
                              "type": "boolean"
                            },
                            "expires_at": {
                              "description": "When the key stops working, RFC 3339 UTC; null when it never expires.",
                              "format": "date-time",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "id": {
                              "description": "Key ID (key_…): manage the key with it. It is not the secret.",
                              "type": "string"
                            },
                            "ip_allowlist": {
                              "description": "IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; [] = any.",
                              "items": {
                                "type": "string"
                              },
                              "type": "array"
                            },
                            "last_used_at": {
                              "description": "About when the key was last used (updated at most hourly); null when never.",
                              "format": "date-time",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "name": {
                              "description": "Your label for the key.",
                              "type": "string"
                            },
                            "object": {
                              "description": "Always api_key.",
                              "enum": [
                                "api_key"
                              ],
                              "type": "string"
                            },
                            "prefix": {
                              "description": "The secret's first characters, to recognize it.",
                              "type": "string"
                            },
                            "previous_secret_expires_at": {
                              "description": "Until then the secret this key had before its last rotation works too (rotate_secret), RFC 3339 UTC; null when none does.",
                              "format": "date-time",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "revoked_at": {
                              "description": "When the key was revoked; null while it is not.",
                              "format": "date-time",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "scopes": {
                              "description": "What the key may call: endpoints (data endpoints), jobs (create, read and cancel jobs; includes jobs:read), jobs:read (read jobs and their results), account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).",
                              "items": {
                                "enum": [
                                  "endpoints",
                                  "jobs",
                                  "jobs:read",
                                  "account:read",
                                  "admin"
                                ],
                                "type": "string"
                              },
                              "type": "array"
                            },
                            "spend_limit": {
                              "description": "The key's spend limit and what it used this interval; null when the key has none.",
                              "properties": {
                                "amount": {
                                  "description": "Most credits the key may spend per interval.",
                                  "type": "integer"
                                },
                                "interval": {
                                  "description": "Calendar day or month, UTC.",
                                  "enum": [
                                    "day",
                                    "month"
                                  ],
                                  "type": "string"
                                },
                                "resets_at": {
                                  "description": "Start of the next interval, RFC 3339 UTC.",
                                  "format": "date-time",
                                  "type": "string"
                                },
                                "used": {
                                  "description": "Credits the key spent this interval, plus what its requests in flight hold.",
                                  "type": "integer"
                                }
                              },
                              "required": [
                                "amount",
                                "interval",
                                "used",
                                "resets_at"
                              ],
                              "type": [
                                "object",
                                "null"
                              ]
                            },
                            "status": {
                              "description": "pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.",
                              "enum": [
                                "active",
                                "pending",
                                "expired",
                                "revoked"
                              ],
                              "type": "string"
                            }
                          },
                          "required": [
                            "object",
                            "id",
                            "name",
                            "status",
                            "prefix",
                            "scopes",
                            "spend_limit",
                            "expires_at",
                            "ip_allowlist",
                            "created_at",
                            "last_used_at",
                            "revoked_at",
                            "dashboard",
                            "previous_secret_expires_at",
                            "created_by_key",
                            "created_by_user"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "available": {
                          "description": "Credits new requests can set aside now: balance minus what requests in flight and unfinished jobs hold. For a busy account it may lag concurrent requests by about a second.",
                          "type": "integer"
                        },
                        "balance": {
                          "description": "Credits the account owns, including those held by requests in flight and unfinished jobs.",
                          "type": "integer"
                        },
                        "created_at": {
                          "description": "When the account was created, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "email": {
                          "description": "The owner's email address: sign-in links, receipts and balance alerts go there.",
                          "type": "string"
                        },
                        "free_credits_skipped": {
                          "description": "Why this account got no free credits when it was confirmed; null when it got them, or isn't confirmed yet. disposable_address: a throwaway mail service. domain_daily_limit, network_daily_limit: too many new accounts today from its email domain, or from its network. mailbox_used: this mailbox already had them. A daily limit is tried again at the next session, on a later day; the others stand. Everything else works as on any account, buying credits included. New values may be added.",
                          "enum": [
                            "disposable_address",
                            "domain_daily_limit",
                            "network_daily_limit",
                            "mailbox_used"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "Account ID (acct_…).",
                          "type": "string"
                        },
                        "keep_response_bodies": {
                          "description": "Whether each request's answer body is kept, for 7 days (GET /v1/requests/{id}/response); off by default.",
                          "type": "boolean"
                        },
                        "low_balance_threshold": {
                          "description": "credits.low fires (event and email) when a request takes the balance from above this to at or below it; null when off.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "max_rps": {
                          "description": "The account's runaway-protection ceiling, in requests per second: a safety limit that stops a runaway client, not a plan limit (plans have no rate limit). Requests above it fail with rate_limited (free) and Retry-After; short bursts above it are admitted (the RateLimit-Policy header states the burst). GET /v1/usage/rate shows how close the account runs to it; ask support to raise it. An account that has never paid has a lower ceiling, which its first payment removes within a minute.",
                          "type": "integer"
                        },
                        "object": {
                          "description": "Always account.",
                          "enum": [
                            "account"
                          ],
                          "type": "string"
                        },
                        "plan": {
                          "description": "Plan ID.",
                          "type": "string"
                        },
                        "status": {
                          "description": "unverified: created by an agent signup whose owner has not confirmed by email yet (no free credits, live keys pending).",
                          "enum": [
                            "active",
                            "unverified"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "email",
                        "status",
                        "plan",
                        "balance",
                        "available",
                        "low_balance_threshold",
                        "max_rps",
                        "keep_response_bodies",
                        "api_key",
                        "free_credits_skipped",
                        "created_at"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get the account, balance and calling key",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Get the account, balance and calling key",
        "tags": [
          "Account"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "patch": {
        "description": "low_balance_threshold: credits.low (an event and an email to the owner) fires once each time a request takes the balance from above it to at or below it; credits.depleted fires when the balance reaches 0 (and the owner is emailed, at most once a day, which no setting turns off). keep_response_bodies: keep each request's response (GET /v1/requests/{id}/response). Absent fields keep their value. Free.\n\n**Auth:** an API key with the `admin` scope, or the dashboard session.",
        "operationId": "account.update",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "keep_response_bodies": {
                    "description": "true keeps the answer body of every request made from now on up to 1 MB each (a longer one is cut), for 7 days: GET /v1/requests/{id}/response returns it. false stops keeping them; bodies already kept are deleted when their time is up. Takes effect within a minute.",
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "low_balance_threshold": {
                    "description": "Credits; null turns credits.low off. Setting it never fires the event by itself: only a request that crosses it does.",
                    "maximum": 1000000000,
                    "minimum": 0,
                    "type": [
                      "integer",
                      "null"
                    ]
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "api_key": {
                          "description": "The key that made this request; null for a dashboard session.",
                          "properties": {
                            "created_at": {
                              "description": "When the key was created, RFC 3339 UTC.",
                              "format": "date-time",
                              "type": "string"
                            },
                            "created_by_key": {
                              "description": "The API key (key_…) that last created this key, gave it the admin scope or rotated it: revoking that key also revokes this one if this one has admin. Null when none did, or a person has rotated it in the dashboard since.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "created_by_user": {
                              "description": "The person (GET /v1/members user_id) who created this key in the dashboard, or whose key created it. They may have left the account since. Null when no person did (an operator, or a key from before this was recorded).",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "dashboard": {
                              "description": "true for the account's built-in dashboard key: the dashboard's playground runs as it (so its requests are logged, counted and billed like any key's). Nobody holds its secret, so it works only from the signed-in dashboard. Only its spend_limit can be changed (to cap what the playground spends live); renaming, rescoping, restricting, rotating or revoking it is forbidden (details.reason dashboard_key). It is made on first use and revoked with the account.",
                              "type": "boolean"
                            },
                            "expires_at": {
                              "description": "When the key stops working, RFC 3339 UTC; null when it never expires.",
                              "format": "date-time",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "id": {
                              "description": "Key ID (key_…): manage the key with it. It is not the secret.",
                              "type": "string"
                            },
                            "ip_allowlist": {
                              "description": "IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; [] = any.",
                              "items": {
                                "type": "string"
                              },
                              "type": "array"
                            },
                            "last_used_at": {
                              "description": "About when the key was last used (updated at most hourly); null when never.",
                              "format": "date-time",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "name": {
                              "description": "Your label for the key.",
                              "type": "string"
                            },
                            "object": {
                              "description": "Always api_key.",
                              "enum": [
                                "api_key"
                              ],
                              "type": "string"
                            },
                            "prefix": {
                              "description": "The secret's first characters, to recognize it.",
                              "type": "string"
                            },
                            "previous_secret_expires_at": {
                              "description": "Until then the secret this key had before its last rotation works too (rotate_secret), RFC 3339 UTC; null when none does.",
                              "format": "date-time",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "revoked_at": {
                              "description": "When the key was revoked; null while it is not.",
                              "format": "date-time",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "scopes": {
                              "description": "What the key may call: endpoints (data endpoints), jobs (create, read and cancel jobs; includes jobs:read), jobs:read (read jobs and their results), account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).",
                              "items": {
                                "enum": [
                                  "endpoints",
                                  "jobs",
                                  "jobs:read",
                                  "account:read",
                                  "admin"
                                ],
                                "type": "string"
                              },
                              "type": "array"
                            },
                            "spend_limit": {
                              "description": "The key's spend limit and what it used this interval; null when the key has none.",
                              "properties": {
                                "amount": {
                                  "description": "Most credits the key may spend per interval.",
                                  "type": "integer"
                                },
                                "interval": {
                                  "description": "Calendar day or month, UTC.",
                                  "enum": [
                                    "day",
                                    "month"
                                  ],
                                  "type": "string"
                                },
                                "resets_at": {
                                  "description": "Start of the next interval, RFC 3339 UTC.",
                                  "format": "date-time",
                                  "type": "string"
                                },
                                "used": {
                                  "description": "Credits the key spent this interval, plus what its requests in flight hold.",
                                  "type": "integer"
                                }
                              },
                              "required": [
                                "amount",
                                "interval",
                                "used",
                                "resets_at"
                              ],
                              "type": [
                                "object",
                                "null"
                              ]
                            },
                            "status": {
                              "description": "pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.",
                              "enum": [
                                "active",
                                "pending",
                                "expired",
                                "revoked"
                              ],
                              "type": "string"
                            }
                          },
                          "required": [
                            "object",
                            "id",
                            "name",
                            "status",
                            "prefix",
                            "scopes",
                            "spend_limit",
                            "expires_at",
                            "ip_allowlist",
                            "created_at",
                            "last_used_at",
                            "revoked_at",
                            "dashboard",
                            "previous_secret_expires_at",
                            "created_by_key",
                            "created_by_user"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "available": {
                          "description": "Credits new requests can set aside now: balance minus what requests in flight and unfinished jobs hold. For a busy account it may lag concurrent requests by about a second.",
                          "type": "integer"
                        },
                        "balance": {
                          "description": "Credits the account owns, including those held by requests in flight and unfinished jobs.",
                          "type": "integer"
                        },
                        "created_at": {
                          "description": "When the account was created, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "email": {
                          "description": "The owner's email address: sign-in links, receipts and balance alerts go there.",
                          "type": "string"
                        },
                        "free_credits_skipped": {
                          "description": "Why this account got no free credits when it was confirmed; null when it got them, or isn't confirmed yet. disposable_address: a throwaway mail service. domain_daily_limit, network_daily_limit: too many new accounts today from its email domain, or from its network. mailbox_used: this mailbox already had them. A daily limit is tried again at the next session, on a later day; the others stand. Everything else works as on any account, buying credits included. New values may be added.",
                          "enum": [
                            "disposable_address",
                            "domain_daily_limit",
                            "network_daily_limit",
                            "mailbox_used"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "Account ID (acct_…).",
                          "type": "string"
                        },
                        "keep_response_bodies": {
                          "description": "Whether each request's answer body is kept, for 7 days (GET /v1/requests/{id}/response); off by default.",
                          "type": "boolean"
                        },
                        "low_balance_threshold": {
                          "description": "credits.low fires (event and email) when a request takes the balance from above this to at or below it; null when off.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "max_rps": {
                          "description": "The account's runaway-protection ceiling, in requests per second: a safety limit that stops a runaway client, not a plan limit (plans have no rate limit). Requests above it fail with rate_limited (free) and Retry-After; short bursts above it are admitted (the RateLimit-Policy header states the burst). GET /v1/usage/rate shows how close the account runs to it; ask support to raise it. An account that has never paid has a lower ceiling, which its first payment removes within a minute.",
                          "type": "integer"
                        },
                        "object": {
                          "description": "Always account.",
                          "enum": [
                            "account"
                          ],
                          "type": "string"
                        },
                        "plan": {
                          "description": "Plan ID.",
                          "type": "string"
                        },
                        "status": {
                          "description": "unverified: created by an agent signup whose owner has not confirmed by email yet (no free credits, live keys pending).",
                          "enum": [
                            "active",
                            "unverified"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "email",
                        "status",
                        "plan",
                        "balance",
                        "available",
                        "low_balance_threshold",
                        "max_rps",
                        "keep_response_bodies",
                        "api_key",
                        "free_credits_skipped",
                        "created_at"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Update account settings",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Update account settings",
        "tags": [
          "Account"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/account/leave": {
      "post": {
        "description": "Takes the signed-in person off the account they act on. The owner can't leave: hand the account over, or delete it. Free.\n\n**Auth:** the dashboard session cookie.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "account.leave",
        "parameters": [
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "deleted": {
                          "description": "Always true.",
                          "type": "boolean"
                        },
                        "id": {
                          "type": "string"
                        },
                        "object": {
                          "description": "The deleted object's type (webhook_endpoint).",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "deleted"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Leave the account",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Leave the account",
        "tags": [
          "Team"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/account/transfer": {
      "post": {
        "description": "Makes a member or admin the owner; the owner becomes an admin, and account email goes to the new owner. The owner only, with a fresh sign-in. Free.\n\n**Auth:** the dashboard session cookie.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "account.transfer",
        "parameters": [
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "user_id": {
                    "description": "The member who becomes the owner (GET /v1/members). The current owner becomes an admin.",
                    "maxLength": 64,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "required": [
                  "user_id"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "email": {
                          "description": "Their verified email address.",
                          "type": "string"
                        },
                        "is_you": {
                          "description": "Whether this is the signed-in person.",
                          "type": "boolean"
                        },
                        "joined_at": {
                          "description": "When they joined the account, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always member.",
                          "enum": [
                            "member"
                          ],
                          "type": "string"
                        },
                        "role": {
                          "description": "owner: everything, including deleting the account and handing it to someone else (exactly one). admin: billing, keys, webhooks, settings and people, never the owner. member: reads the account and uses the playground with a key it is given; changes nothing.",
                          "enum": [
                            "owner",
                            "admin",
                            "member"
                          ],
                          "type": "string"
                        },
                        "user_id": {
                          "description": "The person's ID: change their role or remove them with it.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "user_id",
                        "email",
                        "role",
                        "joined_at",
                        "is_you"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Hand the account to another member",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Hand the account to another member",
        "tags": [
          "Team"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "owner",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/agent_claims/approve": {
      "post": {
        "description": "The approval page calls it. The agent can then collect a key on the account this session acts on, once: its secret exists only in the agent's answer, and the key can never manage the account. Free.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "agent_claims.approve",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "code": {
                    "description": "The code the agent shows, or the one in its link.",
                    "maxLength": 64,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "required": [
                  "code"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "object": {
                          "description": "Always agent_claim_decision.",
                          "enum": [
                            "agent_claim_decision"
                          ],
                          "type": "string"
                        },
                        "redirect_to": {
                          "description": "An OAuth client: where the browser goes next.",
                          "type": "string"
                        },
                        "status": {
                          "description": "What was decided.",
                          "enum": [
                            "approved",
                            "denied"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "status"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Approve an agent's request for a key",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Approve an agent's request for a key",
        "tags": [
          "Signup"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/agent_claims/deny": {
      "post": {
        "description": "The approval page calls it. The request ends for good, and the agent is told. Free.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "agent_claims.deny",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "code": {
                    "description": "The code the agent shows, or the one in its link.",
                    "maxLength": 64,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "required": [
                  "code"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "object": {
                          "description": "Always agent_claim_decision.",
                          "enum": [
                            "agent_claim_decision"
                          ],
                          "type": "string"
                        },
                        "redirect_to": {
                          "description": "An OAuth client: where the browser goes next.",
                          "type": "string"
                        },
                        "status": {
                          "description": "What was decided.",
                          "enum": [
                            "approved",
                            "denied"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "status"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refuse an agent's request for a key",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Refuse an agent's request for a key",
        "tags": [
          "Signup"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/agent_claims/lookup": {
      "post": {
        "description": "The approval page calls it with the code an agent shows its person: what is asking, from where, and what its key could do. Free.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "agent_claims.lookup",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "code": {
                    "description": "The code the agent shows, or the one in its link.",
                    "maxLength": 64,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "required": [
                  "code"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "client_name": {
                          "description": "What the agent calls itself. Nothing verifies it.",
                          "type": "string"
                        },
                        "created_at": {
                          "description": "When it asked, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "expires_at": {
                          "description": "When the request lapses, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "key_name": {
                          "description": "The label its key will have.",
                          "type": "string"
                        },
                        "location": {
                          "description": "Roughly where the request came from: city and country, where known. Absent for an OAuth client, like network.",
                          "type": "string"
                        },
                        "loopback": {
                          "description": "An OAuth client on the person's own computer: the approval goes back to a local port.",
                          "type": "boolean"
                        },
                        "network": {
                          "description": "The network it came from: the client's IPv4 address or IPv6 /64. Absent for an OAuth client: its request comes through the person's own browser.",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always agent_claim.",
                          "enum": [
                            "agent_claim"
                          ],
                          "type": "string"
                        },
                        "redirect_host": {
                          "description": "An OAuth client: the host the approval goes back to.",
                          "type": "string"
                        },
                        "scopes": {
                          "description": "What its key may do.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "user_code": {
                          "description": "The code the agent shows, to compare. Absent for an OAuth client, which shows none.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "key_name",
                        "scopes",
                        "created_at",
                        "expires_at"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "See an agent's request for a key",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "See an agent's request for a key",
        "tags": [
          "Signup"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/agent_signup": {
      "post": {
        "deprecated": true,
        "description": "Deprecated: agents follow /auth.md instead, which emails nobody and also works for an existing account. Send your human's email address and get a key that stays pending until the human confirms by email, which grants the free credits. Agents never get spending power without a human. For an address that already has an account, no keys are made: the owner is emailed a sign-in link to create one in the dashboard, and the answer is 202 with the human signup's object (check your email).\n\n**Auth:** none.",
        "operationId": "agent_signup.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "email": {
                    "description": "Your human's email address: they confirm there before the live key works.",
                    "maxLength": 254,
                    "minLength": 3,
                    "type": "string"
                  },
                  "name": {
                    "description": "Your name as an agent, shown to the human and used as the keys' label: at most 40 ASCII letters, digits, spaces, hyphens, underscores or parentheses, starting with a letter or digit (anything else is invalid_input). Default: \"Agent\".",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "email"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "account_id": {
                          "description": "The new account (unverified until the human confirms).",
                          "type": "string"
                        },
                        "confirmation_expires_at": {
                          "description": "When the confirmation link stops working; then sign up again.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "email": {
                          "description": "Where the confirmation link was sent.",
                          "type": "string"
                        },
                        "free_credits": {
                          "description": "Credits the account gets when the human confirms.",
                          "type": "integer"
                        },
                        "live_key": {
                          "description": "Pending until the human confirms by email; until then it can only read GET /v1/account (poll api_key.status).",
                          "properties": {
                            "created_at": {
                              "description": "When the key was created, RFC 3339 UTC.",
                              "format": "date-time",
                              "type": "string"
                            },
                            "created_by_key": {
                              "description": "The API key (key_…) that last created this key, gave it the admin scope or rotated it: revoking that key also revokes this one if this one has admin. Null when none did, or a person has rotated it in the dashboard since.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "created_by_user": {
                              "description": "The person (GET /v1/members user_id) who created this key in the dashboard, or whose key created it. They may have left the account since. Null when no person did (an operator, or a key from before this was recorded).",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "dashboard": {
                              "description": "true for the account's built-in dashboard key: the dashboard's playground runs as it (so its requests are logged, counted and billed like any key's). Nobody holds its secret, so it works only from the signed-in dashboard. Only its spend_limit can be changed (to cap what the playground spends live); renaming, rescoping, restricting, rotating or revoking it is forbidden (details.reason dashboard_key). It is made on first use and revoked with the account.",
                              "type": "boolean"
                            },
                            "expires_at": {
                              "description": "When the key stops working, RFC 3339 UTC; null when it never expires.",
                              "format": "date-time",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "id": {
                              "description": "Key ID (key_…): manage the key with it. It is not the secret.",
                              "type": "string"
                            },
                            "ip_allowlist": {
                              "description": "IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; [] = any.",
                              "items": {
                                "type": "string"
                              },
                              "type": "array"
                            },
                            "last_used_at": {
                              "description": "About when the key was last used (updated at most hourly); null when never.",
                              "format": "date-time",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "name": {
                              "description": "Your label for the key.",
                              "type": "string"
                            },
                            "object": {
                              "description": "Always api_key.",
                              "enum": [
                                "api_key"
                              ],
                              "type": "string"
                            },
                            "prefix": {
                              "description": "The secret's first characters, to recognize it.",
                              "type": "string"
                            },
                            "previous_secret_expires_at": {
                              "description": "Until then the secret this key had before its last rotation works too (rotate_secret), RFC 3339 UTC; null when none does.",
                              "format": "date-time",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "revoked_at": {
                              "description": "When the key was revoked; null while it is not.",
                              "format": "date-time",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "scopes": {
                              "description": "What the key may call: endpoints (data endpoints), jobs (create, read and cancel jobs; includes jobs:read), jobs:read (read jobs and their results), account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).",
                              "items": {
                                "enum": [
                                  "endpoints",
                                  "jobs",
                                  "jobs:read",
                                  "account:read",
                                  "admin"
                                ],
                                "type": "string"
                              },
                              "type": "array"
                            },
                            "secret": {
                              "description": "The key itself: send it in the x-api-key header. Shown only once: store it now.",
                              "type": "string"
                            },
                            "spend_limit": {
                              "description": "The key's spend limit and what it used this interval; null when the key has none.",
                              "properties": {
                                "amount": {
                                  "description": "Most credits the key may spend per interval.",
                                  "type": "integer"
                                },
                                "interval": {
                                  "description": "Calendar day or month, UTC.",
                                  "enum": [
                                    "day",
                                    "month"
                                  ],
                                  "type": "string"
                                },
                                "resets_at": {
                                  "description": "Start of the next interval, RFC 3339 UTC.",
                                  "format": "date-time",
                                  "type": "string"
                                },
                                "used": {
                                  "description": "Credits the key spent this interval, plus what its requests in flight hold.",
                                  "type": "integer"
                                }
                              },
                              "required": [
                                "amount",
                                "interval",
                                "used",
                                "resets_at"
                              ],
                              "type": [
                                "object",
                                "null"
                              ]
                            },
                            "status": {
                              "description": "pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.",
                              "enum": [
                                "active",
                                "pending",
                                "expired",
                                "revoked"
                              ],
                              "type": "string"
                            }
                          },
                          "required": [
                            "object",
                            "id",
                            "name",
                            "status",
                            "prefix",
                            "scopes",
                            "spend_limit",
                            "expires_at",
                            "ip_allowlist",
                            "created_at",
                            "last_used_at",
                            "revoked_at",
                            "dashboard",
                            "previous_secret_expires_at",
                            "created_by_key",
                            "created_by_user",
                            "secret"
                          ],
                          "type": "object"
                        },
                        "object": {
                          "description": "Always agent_signup.",
                          "enum": [
                            "agent_signup"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "account_id",
                        "email",
                        "free_credits",
                        "confirmation_expires_at",
                        "live_key"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Sign up as an agent: a key that works on confirm",
            "headers": {
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "email": {
                          "description": "Where the link was sent.",
                          "type": "string"
                        },
                        "expires_at": {
                          "description": "When the link stops working, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always signup.",
                          "enum": [
                            "signup"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "email",
                        "expires_at"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The address already has an account: no keys were made; its owner was emailed a sign-in link to create a key for you in the dashboard. Ask them to check their email.",
            "headers": {
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [],
        "summary": "Sign up as an agent: a key that works on confirm",
        "tags": [
          "Signup"
        ],
        "x-socialtap-auth": {
          "auth": "none",
          "role": "",
          "scope": ""
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/amazon/deal_products": {
      "get": {
        "description": "Returns Amazon's Today's Deals on any Amazon marketplace, all deals or one category's, in Amazon's own order. Each product has its deal price and the list or typical price it beats, the deal's type, badge and end time, the share of a lightning deal claimed, and any coupon's price. You also get the title, image, brand and star rating with its exact count.\n\nReturns `{data, page, meta}`: `data` holds up to 100 `Product` items (the shared schema, the same on every platform), Amazon's Today's Deals order (its own ranking, as the grid shows it). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/amazon/deal_products/ (Markdown: https://socialtap.dev/docs/reference/amazon/deal_products/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/amazon/deal_products/index.md)",
          "url": "https://socialtap.dev/docs/reference/amazon/deal_products/"
        },
        "operationId": "amazon.deal_products.list",
        "parameters": [
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace whose deals to read, by country: US (amazon.com), GB (amazon.co.uk), DE, JP, IN, … Prices are that marketplace's, in its currency. Default: the category link's marketplace, else US. A country other than the category link's is refused.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace whose deals to read, by country: US (amazon.com), GB (amazon.co.uk), DE, JP, IN, … Prices are that marketplace's, in its currency. Default: the category link's marketplace, else US. A country other than the category link's is refused.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only the deals of one category: its browse node ID (172282 is Electronics on amazon.com), or a link that names one: a category link (amazon.com/b?node=172282), a search link filtered to a department, or a Today's Deals link with a department picked (its price and discount filters aren't applied). A product's platform_specific.amazon.categories[].id and a deal's platform_specific.amazon.deal.department_ids are such IDs. Omit for every deal. Browse nodes are each marketplace's own.",
            "example": "172282",
            "in": "query",
            "name": "category",
            "schema": {
              "description": "Only the deals of one category: its browse node ID (172282 is Electronics on amazon.com), or a link that names one: a category link (amazon.com/b?node=172282), a search link filtered to a department, or a Today's Deals link with a department picked (its price and discount filters aren't applied). A product's platform_specific.amazon.categories[].id and a deal's platform_specific.amazon.deal.department_ids are such IDs. Omit for every deal. Browse nodes are each marketplace's own.",
              "examples": [
                "172282"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 100,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "platform_specific.amazon.rating",
                            "platform_specific.amazon.metrics.rating_distribution"
                          ],
                          "attributes": [],
                          "availability": "in_stock",
                          "category": null,
                          "category_id": null,
                          "condition": "new",
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "B0G2D1R15Q",
                          "max_price": null,
                          "media": [],
                          "original_price": 99.99,
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "availability_label": null,
                              "best_sellers_ranks": [],
                              "brand": "Ring",
                              "categories": [],
                              "contributors": [],
                              "deal": {
                                "badge": "60% off",
                                "claimed_percent": null,
                                "coupon_id": null,
                                "coupon_price": null,
                                "department_ids": [
                                  "16333372011",
                                  "172282",
                                  "493964"
                                ],
                                "ends_at": null,
                                "id": "d0d0a6d6",
                                "label": "Early Black Friday Deal",
                                "original_price_label": "typical",
                                "status": "available",
                                "type": "best_deal"
                              },
                              "features": [],
                              "is_sponsored": null,
                              "metrics": {
                                "bought_past_month_count": null,
                                "offer_count": null,
                                "rating_count": 8694,
                                "rating_distribution": {
                                  "five_star_count": 6260,
                                  "four_star_count": 696,
                                  "one_star_count": 956,
                                  "three_star_count": 522,
                                  "two_star_count": 261
                                }
                              },
                              "parent_asin": null,
                              "rank": null,
                              "rating": 4.2,
                              "ships_from": null,
                              "variants": []
                            }
                          },
                          "price": 39.99,
                          "seller": null,
                          "shipping": {
                            "fee": null,
                            "is_offered": null
                          },
                          "thumbnail_url": "https://m.media-amazon.com/images/I/51kY6VkfPeL.jpg",
                          "title": "Ring Battery Doorbell 2K (newest model), Matte Mocha",
                          "type": "product",
                          "unknown_fields": [
                            "media",
                            "attributes",
                            "platform_specific.amazon.contributors"
                          ],
                          "url": "https://www.amazon.com/dp/B0G2D1R15Q"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.amazon.rating",
                            "platform_specific.amazon.metrics.rating_distribution"
                          ],
                          "attributes": [],
                          "availability": "in_stock",
                          "category": null,
                          "category_id": null,
                          "condition": "new",
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "B0CHDM8VVZ",
                          "max_price": null,
                          "media": [],
                          "original_price": 399,
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "availability_label": null,
                              "best_sellers_ranks": [],
                              "brand": "Bambu Lab",
                              "categories": [],
                              "contributors": [],
                              "deal": {
                                "badge": "13% off",
                                "claimed_percent": null,
                                "coupon_id": null,
                                "coupon_price": null,
                                "department_ids": [
                                  "16310091",
                                  "16310161"
                                ],
                                "ends_at": null,
                                "id": "23721016",
                                "label": "Limited time deal",
                                "original_price_label": "list",
                                "status": "available",
                                "type": "best_deal"
                              },
                              "features": [],
                              "is_sponsored": null,
                              "metrics": {
                                "bought_past_month_count": null,
                                "offer_count": null,
                                "rating_count": 444,
                                "rating_distribution": {
                                  "five_star_count": 355,
                                  "four_star_count": 22,
                                  "one_star_count": 36,
                                  "three_star_count": 27,
                                  "two_star_count": 4
                                }
                              },
                              "parent_asin": null,
                              "rank": null,
                              "rating": 4.5,
                              "ships_from": null,
                              "variants": []
                            }
                          },
                          "price": 349,
                          "seller": null,
                          "shipping": {
                            "fee": null,
                            "is_offered": null
                          },
                          "thumbnail_url": "https://m.media-amazon.com/images/I/61IXKmM4f9L.jpg",
                          "title": "Bambu Lab P1S 3D Printer, Ready-to-Use FDM 3D Printer | Beginner-Friendly Ecosystem with MakerWorld Model Library, Enclosed CoreXY, High Speed & Precision Printing",
                          "type": "product",
                          "unknown_fields": [
                            "media",
                            "attributes",
                            "platform_specific.amazon.contributors"
                          ],
                          "url": "https://www.amazon.com/dp/B0CHDM8VVZ"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.amazon.rating",
                            "platform_specific.amazon.metrics.rating_distribution"
                          ],
                          "attributes": [],
                          "availability": "in_stock",
                          "category": null,
                          "category_id": null,
                          "condition": "new",
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "B0FQV6LMVX",
                          "max_price": null,
                          "media": [],
                          "original_price": 1199,
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "availability_label": null,
                              "best_sellers_ranks": [],
                              "brand": "EF ECOFLOW",
                              "categories": [],
                              "contributors": [],
                              "deal": {
                                "badge": "27% off",
                                "claimed_percent": null,
                                "coupon_id": null,
                                "coupon_price": null,
                                "department_ids": [
                                  "16310091",
                                  "16310161",
                                  "2972638011"
                                ],
                                "ends_at": null,
                                "id": "ee891d27",
                                "label": "Limited time deal",
                                "original_price_label": "list",
                                "status": "available",
                                "type": "best_deal"
                              },
                              "features": [],
                              "is_sponsored": null,
                              "metrics": {
                                "bought_past_month_count": null,
                                "offer_count": null,
                                "rating_count": 661,
                                "rating_distribution": {
                                  "five_star_count": 582,
                                  "four_star_count": 40,
                                  "one_star_count": 26,
                                  "three_star_count": 13,
                                  "two_star_count": 0
                                }
                              },
                              "parent_asin": null,
                              "rank": null,
                              "rating": 4.7,
                              "ships_from": null,
                              "variants": []
                            }
                          },
                          "price": 878.99,
                          "seller": null,
                          "shipping": {
                            "fee": null,
                            "is_offered": null
                          },
                          "thumbnail_url": "https://m.media-amazon.com/images/I/61XcQS5XuML.jpg",
                          "title": "EF ECOFLOW DELTA 3 Max Portable Power Station, 2048Wh LFP Battery, 2400W | 3400W X-Boost Output, Ultra-Fast 0-80% Charging in 1.13 Hr, Home Backup & RV Camping, Solar Generator (Solar Panel Optional)",
                          "type": "product",
                          "unknown_fields": [
                            "media",
                            "attributes",
                            "platform_specific.amazon.contributors"
                          ],
                          "url": "https://www.amazon.com/dp/B0FQV6LMVX"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "amazon",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/AmazonDeal_productsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Today's Deals with deal price, badge and end time",
        "tags": [
          "Amazon"
        ],
        "x-socialtap-endpoint": "amazon.deal_products",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Amazon's Today's Deals order (its own ranking, as the grid shows it)",
          "page_max": 100,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "product",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/amazon/offers": {
      "get": {
        "description": "Returns every seller's offer of an Amazon product, from its link, short link or ASIN, on any Amazon marketplace. Each offer has the seller with its ID, star rating and rating count, the price and list price, the condition with the seller's notes, the shipping fee and delivery dates, and who ships it. The buy box offer comes first, marked featured when Amazon's offers panel pins it; a product nobody sells right now returns an empty list.\n\nReturns `{data, page, meta}`: `data` holds up to 11 `Offer` items (the shared schema, the same on every platform), The buy box offer first, then every other offer in Amazon's order: by price plus delivery, lowest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/amazon/offers/ (Markdown: https://socialtap.dev/docs/reference/amazon/offers/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/amazon/offers/index.md)",
          "url": "https://socialtap.dev/docs/reference/amazon/offers/"
        },
        "operationId": "amazon.offers.list",
        "parameters": [
          {
            "description": "The product: its link on any Amazon marketplace (amazon.com/dp/B0FQFB8FMG, with or without the title before /dp/, /gp/product/, /gp/aw/d/, /gp/offer-listing/, /product-reviews/ and the older /exec/obidos/ASIN/ links), a short link (amzn.to, a.co/d/, amzn.eu/d/, amzn.asia/d/, amzn.com), or its ASIN alone (B0FQFB8FMG, or a book's ISBN-10).",
            "example": "https://www.amazon.com/Apple-AirPods-Pro-3/dp/B0FQFB8FMG",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The product: its link on any Amazon marketplace (amazon.com/dp/B0FQFB8FMG, with or without the title before /dp/, /gp/product/, /gp/aw/d/, /gp/offer-listing/, /product-reviews/ and the older /exec/obidos/ASIN/ links), a short link (amzn.to, a.co/d/, amzn.eu/d/, amzn.asia/d/, amzn.com), or its ASIN alone (B0FQFB8FMG, or a book's ISBN-10).",
              "examples": [
                "https://www.amazon.com/dp/B0FQFB8FMG"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to read, by country: US (amazon.com), GB (amazon.co.uk), DE, JP, IN, … Offers, prices and delivery are that marketplace's. Default: the link's marketplace, else US.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to read, by country: US (amazon.com), GB (amazon.co.uk), DE, JP, IN, … Offers, prices and delivery are that marketplace's. Default: the link's marketplace, else US.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 11,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 11,
              "maximum": 11,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "shipping.earliest_delivery_at",
                            "shipping.latest_delivery_at"
                          ],
                          "availability": "in_stock",
                          "condition": "new",
                          "condition_label": "New",
                          "country_code": "US",
                          "currency": "USD",
                          "id": "B0FQFB8FMG:ATVPDKIKX0DER:new",
                          "is_featured": true,
                          "metrics": {
                            "seller_rating_count": null
                          },
                          "original_price": 249,
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "condition_note": null,
                              "is_fulfilled_by_amazon": true,
                              "seller_positive_percent": null,
                              "ships_from": "Amazon.com"
                            }
                          },
                          "price": 199,
                          "product_id": "B0FQFB8FMG",
                          "seller": {
                            "avatar_url": null,
                            "display_name": "Amazon.com",
                            "id": "ATVPDKIKX0DER",
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "seller_rating": null,
                          "shipping": {
                            "earliest_delivery_at": "2026-11-15T00:00:00Z",
                            "fee": 0,
                            "is_offered": true,
                            "latest_delivery_at": "2026-11-15T00:00:00Z"
                          },
                          "title": null,
                          "unknown_fields": [],
                          "url": "https://www.amazon.com/dp/B0FQFB8FMG?smid=ATVPDKIKX0DER"
                        },
                        {
                          "approximate_fields": [
                            "shipping.earliest_delivery_at",
                            "shipping.latest_delivery_at"
                          ],
                          "availability": "in_stock",
                          "condition": "used",
                          "condition_label": "Used - Acceptable",
                          "country_code": "US",
                          "currency": "USD",
                          "id": "B0FQFB8FMG:amazon-resale:used-acceptable",
                          "is_featured": false,
                          "metrics": {
                            "seller_rating_count": null
                          },
                          "original_price": null,
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "condition_note": "Minor packaging damage observed during inspection.",
                              "is_fulfilled_by_amazon": true,
                              "seller_positive_percent": null,
                              "ships_from": "Amazon.com"
                            }
                          },
                          "price": 183.08,
                          "product_id": "B0FQFB8FMG",
                          "seller": {
                            "avatar_url": null,
                            "display_name": "Amazon Resale",
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "seller_rating": null,
                          "shipping": {
                            "earliest_delivery_at": "2026-11-15T00:00:00Z",
                            "fee": 0,
                            "is_offered": true,
                            "latest_delivery_at": "2026-11-15T00:00:00Z"
                          },
                          "title": null,
                          "unknown_fields": [],
                          "url": null
                        },
                        {
                          "approximate_fields": [
                            "shipping.earliest_delivery_at",
                            "shipping.latest_delivery_at"
                          ],
                          "availability": "in_stock",
                          "condition": "used",
                          "condition_label": "Used - Good",
                          "country_code": "US",
                          "currency": "USD",
                          "id": "B0FQFB8FMG:amazon-resale:used-good",
                          "is_featured": false,
                          "metrics": {
                            "seller_rating_count": null
                          },
                          "original_price": null,
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "condition_note": "Item may not come in original packaging.",
                              "is_fulfilled_by_amazon": true,
                              "seller_positive_percent": null,
                              "ships_from": "Amazon.com"
                            }
                          },
                          "price": 185.07,
                          "product_id": "B0FQFB8FMG",
                          "seller": {
                            "avatar_url": null,
                            "display_name": "Amazon Resale",
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "seller_rating": null,
                          "shipping": {
                            "earliest_delivery_at": "2026-11-15T00:00:00Z",
                            "fee": 0,
                            "is_offered": true,
                            "latest_delivery_at": "2026-11-15T00:00:00Z"
                          },
                          "title": null,
                          "unknown_fields": [],
                          "url": null
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "amazon",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "product",
                          "id": "B0FQFB8FMG",
                          "url": "https://www.amazon.com/dp/B0FQFB8FMG"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "end"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/AmazonOffersResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Every seller's price, condition and delivery for an ASIN",
        "tags": [
          "Amazon"
        ],
        "x-socialtap-endpoint": "amazon.offers",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "The buy box offer first, then every other offer in Amazon's order: by price plus delivery, lowest first",
          "page_max": 11,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "offer",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/amazon/product": {
      "get": {
        "description": "Returns an Amazon product from its link, short link or ASIN, on any Amazon marketplace. You get the title, the current price with the list price it is discounted from, the seller and who ships it, stock, the star rating with its exact count and breakdown, and the monthly sales badge. It also has the Best Sellers Rank, brand or authors, the bullets and description, every specification, all images and videos, and every variation's ASIN.\n\nReturns `{data, meta}`: `data` is a `Product` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/amazon/product/ (Markdown: https://socialtap.dev/docs/reference/amazon/product/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/amazon/product/index.md)",
          "url": "https://socialtap.dev/docs/reference/amazon/product/"
        },
        "operationId": "amazon.product.get",
        "parameters": [
          {
            "description": "The product: its link on any Amazon marketplace (amazon.com/dp/B0FQFB8FMG, with or without the title before /dp/, /gp/product/, /gp/aw/d/, /product-reviews/ and the older /exec/obidos/ASIN/ links), a short link (amzn.to, a.co/d/, amzn.eu/d/, amzn.asia/d/, amzn.com), or its ASIN alone (B0FQFB8FMG, or a book's ISBN-10).",
            "example": "https://www.amazon.com/Apple-AirPods-Pro-3/dp/B0FQFB8FMG",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The product: its link on any Amazon marketplace (amazon.com/dp/B0FQFB8FMG, with or without the title before /dp/, /gp/product/, /gp/aw/d/, /product-reviews/ and the older /exec/obidos/ASIN/ links), a short link (amzn.to, a.co/d/, amzn.eu/d/, amzn.asia/d/, amzn.com), or its ASIN alone (B0FQFB8FMG, or a book's ISBN-10).",
              "examples": [
                "https://www.amazon.com/dp/B0FQFB8FMG"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to read, by country: US (amazon.com), GB (amazon.co.uk), DE, JP, IN, … Prices, stock and sellers are that marketplace's. Default: the link's marketplace, else US.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to read, by country: US (amazon.com), GB (amazon.co.uk), DE, JP, IN, … Prices, stock and sellers are that marketplace's. Default: the link's marketplace, else US.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "platform_specific.amazon.rating",
                          "platform_specific.amazon.metrics.rating_distribution",
                          "platform_specific.amazon.metrics.bought_past_month_count"
                        ],
                        "attributes": [
                          {
                            "name": "Brand",
                            "value": "Apple"
                          },
                          {
                            "name": "Color",
                            "value": "White"
                          },
                          {
                            "name": "Ear Placement",
                            "value": "In Ear"
                          }
                        ],
                        "availability": "in_stock",
                        "category": null,
                        "category_id": null,
                        "condition": "new",
                        "condition_label": null,
                        "country_code": "US",
                        "currency": "USD",
                        "description": "WORLD’S BEST IN-EAR ACTIVE NOISE CANCELLATION — Removes up to 2x more unwanted noise than AirPods Pro 2* so you can stay fully immersed in the moment.*\n\nBREAKTHROUGH AUDIO PERFORMANCE — Experience breathtaking, three-dimensional audio with AirPods Pro 3. A new acoustic architectu…",
                        "id": "B0FQFB8FMG",
                        "max_price": null,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": null,
                            "expires_at": null,
                            "height": null,
                            "thumbnail_url": null,
                            "type": "image",
                            "url": "https://m.media-amazon.com/images/I/61solmQSSlL._AC_SL1500_.jpg",
                            "width": null
                          },
                          {
                            "alt_text": null,
                            "duration_ms": null,
                            "expires_at": null,
                            "height": null,
                            "thumbnail_url": null,
                            "type": "image",
                            "url": "https://m.media-amazon.com/images/I/71dt0UurPZL._AC_SL1500_.jpg",
                            "width": null
                          },
                          {
                            "alt_text": null,
                            "duration_ms": null,
                            "expires_at": null,
                            "height": null,
                            "thumbnail_url": null,
                            "type": "image",
                            "url": "https://m.media-amazon.com/images/I/61pH6X22khL._AC_SL1500_.jpg",
                            "width": null
                          }
                        ],
                        "original_price": 249,
                        "platform": "amazon",
                        "platform_specific": {
                          "amazon": {
                            "availability_label": "In Stock",
                            "best_sellers_ranks": [],
                            "brand": "Apple",
                            "categories": [],
                            "contributors": [],
                            "deal": null,
                            "features": [
                              "WORLD’S BEST IN-EAR ACTIVE NOISE CANCELLATION — Removes up to 2x more unwanted noise than AirPods Pro 2* so you can stay fully immersed in the moment.*",
                              "BREAKTHROUGH AUDIO PERFORMANCE — Experience breathtaking, three-dimensional audio with AirPods Pro 3. A new acoustic architecture delivers transformed bass, detailed clarity so you can hear every instrument, and stunningly vivid vocals.",
                              "HEART RATE SENSING — Built-in heart rate sensing lets you track your heart rate and calories burned for up to 50 different workout types.* With iPhone, you will have access to the Move ring, step count, and the new Workout Buddy,* powered by Apple Intelligence.*"
                            ],
                            "is_sponsored": null,
                            "metrics": {
                              "bought_past_month_count": 10000,
                              "offer_count": 11,
                              "rating_count": 17730,
                              "rating_distribution": {
                                "five_star_count": 14007,
                                "four_star_count": 1241,
                                "one_star_count": 1596,
                                "three_star_count": 532,
                                "two_star_count": 355
                              }
                            },
                            "parent_asin": null,
                            "rank": null,
                            "rating": 4.4,
                            "ships_from": "Amazon.com",
                            "variants": []
                          }
                        },
                        "price": 199,
                        "seller": {
                          "avatar_url": null,
                          "display_name": "Amazon.com",
                          "id": "ATVPDKIKX0DER",
                          "is_verified": null,
                          "url": null,
                          "username": null
                        },
                        "shipping": {
                          "fee": 0,
                          "is_offered": true
                        },
                        "thumbnail_url": "https://m.media-amazon.com/images/I/61solmQSSlL._AC_SL1500_.jpg",
                        "title": "Apple AirPods Pro 3 Wireless Earbuds with Active Noise Cancellation",
                        "type": "product",
                        "unknown_fields": [],
                        "url": "https://www.amazon.com/dp/B0FQFB8FMG"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "amazon",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "product",
                          "id": "B0FQFB8FMG",
                          "url": "https://www.amazon.com/dp/B0FQFB8FMG"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/AmazonProductResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Price, rating, monthly sales and specs by ASIN",
        "tags": [
          "Amazon"
        ],
        "x-socialtap-endpoint": "amazon.product",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "product",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/amazon/reviews": {
      "get": {
        "description": "Returns the top customer reviews an Amazon product page shows, from the product's link, short link or ASIN, on any Amazon marketplace outside the US. Each review has its star rating, title, full text and language, the reviewer with their profile link, the variation bought, whether the purchase is verified, how many people found it helpful, its photos and videos, and the date and country it was written in.\n\nReturns `{data, page, meta}`: `data` holds up to 20 `Review` items (the shared schema, the same on every platform), Amazon's top reviews: the marketplace's own first, then other countries'. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/amazon/reviews/ (Markdown: https://socialtap.dev/docs/reference/amazon/reviews/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/amazon/reviews/index.md)",
          "url": "https://socialtap.dev/docs/reference/amazon/reviews/"
        },
        "operationId": "amazon.reviews.list",
        "parameters": [
          {
            "description": "The product: its link on any Amazon marketplace (amazon.co.uk/dp/B003AIF4Q4, with or without the title before /dp/, /gp/product/, /gp/aw/d/, /product-reviews/ and the older /exec/obidos/ASIN/ links), a short link (amzn.to, a.co/d/, amzn.eu/d/, amzn.asia/d/, amzn.com), or its ASIN alone (B003AIF4Q4, or a book's ISBN-10) with country.",
            "example": "https://www.amazon.co.uk/dp/0735211299",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The product: its link on any Amazon marketplace (amazon.co.uk/dp/B003AIF4Q4, with or without the title before /dp/, /gp/product/, /gp/aw/d/, /product-reviews/ and the older /exec/obidos/ASIN/ links), a short link (amzn.to, a.co/d/, amzn.eu/d/, amzn.asia/d/, amzn.com), or its ASIN alone (B003AIF4Q4, or a book's ISBN-10) with country.",
              "examples": [
                "https://www.amazon.co.uk/dp/B003AIF4Q4"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to read, by country: GB (amazon.co.uk), DE, FR, IT, ES, CA, JP, IN, AU, … Each shows its own customers' top reviews first, then top reviews from other countries. Default: the link's marketplace, else US (amazon.com, which shows reviews only to signed-in visitors).",
            "example": "GB",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to read, by country: GB (amazon.co.uk), DE, FR, IT, ES, CA, JP, IN, AU, … Each shows its own customers' top reviews first, then top reviews from other countries. Default: the link's marketplace, else US (amazon.com, which shows reviews only to signed-in visitors).",
              "examples": [
                "GB"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 20,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": null,
                            "display_name": "A B Hann",
                            "id": "amzn1.account.AFOIQIFVHELUIDZNA3PZAAHUQH6A",
                            "is_verified": null,
                            "url": "https://www.amazon.co.uk/gp/profile/amzn1.account.AFOIQIFVHELUIDZNA3PZAAHUQH6A",
                            "username": null
                          },
                          "country_code": "GB",
                          "id": "R26NWF54CTYPDH",
                          "is_incentivized": false,
                          "is_verified_purchase": true,
                          "language": "en",
                          "media": [],
                          "metrics": {
                            "helpful_count": 25
                          },
                          "platform": "amazon",
                          "platform_specific": {},
                          "product_id": "0735211299",
                          "published_at": "2026-03-04T00:00:00Z",
                          "rating": 5,
                          "text": "Atomic Habits completely changed the way I think about progress and self-improvement. Instead of focusing on huge life overhauls, it breaks everything down into small, practical changes that actually feel manageable.\n\nWhat I appreciated most is how actionable the advice is. The s…",
                          "title": "Simple Ideas, Powerful Results",
                          "unknown_fields": [],
                          "url": "https://www.amazon.co.uk/gp/customer-reviews/R26NWF54CTYPDH",
                          "variant_id": "1847941834",
                          "variant_title": "Format: Paperback"
                        },
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": "https://m.media-amazon.com/images/S/amazon-avatars-global/ce2aa141-d825-444f-859e-e735d5e639d2._CR0%2C0%2C500%2C500_SX460_SX48_.jpeg",
                            "display_name": "John M",
                            "id": "amzn1.account.AGRCKXSEGOJY6VKWXVUZBOSJ35SA",
                            "is_verified": null,
                            "url": "https://www.amazon.co.uk/gp/profile/amzn1.account.AGRCKXSEGOJY6VKWXVUZBOSJ35SA",
                            "username": null
                          },
                          "country_code": "GB",
                          "id": "R2R5XY27STL9YL",
                          "is_incentivized": false,
                          "is_verified_purchase": true,
                          "language": "en",
                          "media": [],
                          "metrics": {
                            "helpful_count": 12
                          },
                          "platform": "amazon",
                          "platform_specific": {},
                          "product_id": "0735211299",
                          "published_at": "2026-09-10T00:00:00Z",
                          "rating": 5,
                          "text": "Atomic Habits has genuinely changed the way I look at several areas of my life. Rather than focusing on dramatic overnight transformations, it helped me understand the power of small, consistent actions and how they gradually shape our identity and future.\n\nOne of the most impact…",
                          "title": "A Powerful Book That Changed My Outlook",
                          "unknown_fields": [],
                          "url": "https://www.amazon.co.uk/gp/customer-reviews/R2R5XY27STL9YL",
                          "variant_id": "1847941834",
                          "variant_title": "Format: Paperback"
                        },
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": null,
                            "display_name": "Rodrigo Ferreira",
                            "id": "amzn1.account.AECVB7TIUUBFDS43YI24MB2B6ILQ",
                            "is_verified": null,
                            "url": "https://www.amazon.co.uk/gp/profile/amzn1.account.AECVB7TIUUBFDS43YI24MB2B6ILQ",
                            "username": null
                          },
                          "country_code": "GB",
                          "id": "RQW3OS75ABF74",
                          "is_incentivized": false,
                          "is_verified_purchase": true,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://m.media-amazon.com/images/I/61ezPtvAdKL._SY500_.jpg",
                              "type": "image",
                              "url": "https://m.media-amazon.com/images/I/61ezPtvAdKL.jpg",
                              "width": null
                            },
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://m.media-amazon.com/images/I/517WaERYwEL._SY500_.jpg",
                              "type": "image",
                              "url": "https://m.media-amazon.com/images/I/517WaERYwEL.jpg",
                              "width": null
                            },
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://m.media-amazon.com/images/I/61+X8YMvgVL._SY500_.jpg",
                              "type": "image",
                              "url": "https://m.media-amazon.com/images/I/61+X8YMvgVL.jpg",
                              "width": null
                            }
                          ],
                          "metrics": {
                            "helpful_count": 7
                          },
                          "platform": "amazon",
                          "platform_specific": {},
                          "product_id": "0735211299",
                          "published_at": "2026-07-09T00:00:00Z",
                          "rating": 4,
                          "text": "I haven’t finished the entire book yet, but I’ve read enough to understand its core message. The idea that tiny, consistent changes compound into major long‑term transformation is genuinely useful, and it’s helped me pay more attention to small wins I normally overlook. I’ve alre…",
                          "title": "Helpful framework for small improvements, but oversimplifies the mental side of habit change",
                          "unknown_fields": [],
                          "url": "https://www.amazon.co.uk/gp/customer-reviews/RQW3OS75ABF74",
                          "variant_id": "1847941834",
                          "variant_title": "Format: Paperback"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "amazon",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "product",
                          "id": "0735211299",
                          "url": "https://www.amazon.co.uk/dp/0735211299"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/AmazonReviewsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Top customer reviews of a product, by marketplace",
        "tags": [
          "Amazon"
        ],
        "x-socialtap-endpoint": "amazon.reviews",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Amazon's top reviews: the marketplace's own first, then other countries'",
          "page_max": 20,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "review",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/amazon/search_products": {
      "get": {
        "description": "Returns Amazon's search results for a keyword, on any Amazon marketplace, page by page. Each product has its ASIN, title, price with the list price it is discounted from, image, star rating with the exact number of ratings, and the monthly sales badge. Results that show a brand line also carry the brand, and sponsored results are flagged. Sort by relevance, price, newest or best sellers.\n\nReturns `{data, page, meta}`: `data` holds up to 60 `Product` items (the shared schema, the same on every platform), Amazon's Featured order, sponsored results among them with sort=relevance (the default), Amazon's Newest Arrivals: the most recently listed first with sort=newest, Amazon's Best Sellers order: the most bought first with sort=popular, the lowest price first with sort=price_asc, the highest price first with sort=price_desc. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/amazon/search_products/ (Markdown: https://socialtap.dev/docs/reference/amazon/search_products/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/amazon/search_products/index.md)",
          "url": "https://socialtap.dev/docs/reference/amazon/search_products/"
        },
        "operationId": "amazon.search_products.list",
        "parameters": [
          {
            "description": "What to search for, as typed into Amazon's search box: keywords, a brand, a model or an ISBN. An Amazon search results link searches its keywords on its marketplace.",
            "example": "wireless earbuds",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to search for, as typed into Amazon's search box: keywords, a brand, a model or an ISBN. An Amazon search results link searches its keywords on its marketplace.",
              "examples": [
                "wireless earbuds"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to search, by country: US (amazon.com), GB (amazon.co.uk), DE, JP, IN, … Results, prices and currency are that marketplace's. Default: US.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to search, by country: US (amazon.com), GB (amazon.co.uk), DE, JP, IN, … Results, prices and currency are that marketplace's. Default: US.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Order of the results. relevance (default): Amazon's Featured order. price_asc, price_desc: the lowest or the highest price first. newest: Amazon's Newest Arrivals. popular: Amazon's Best Sellers order.",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "relevance",
              "description": "Order of the results. relevance (default): Amazon's Featured order. price_asc, price_desc: the lowest or the highest price first. newest: Amazon's Newest Arrivals. popular: Amazon's Best Sellers order.",
              "enum": [
                "relevance",
                "price_asc",
                "price_desc",
                "newest",
                "popular"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 60,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 60,
              "maximum": 60,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "platform_specific.amazon.rating",
                            "platform_specific.amazon.metrics.bought_past_month_count"
                          ],
                          "attributes": [],
                          "availability": null,
                          "category": null,
                          "category_id": null,
                          "condition": null,
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "B0H8NFRF3S",
                          "max_price": null,
                          "media": [],
                          "original_price": 199.99,
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "availability_label": null,
                              "best_sellers_ranks": [],
                              "brand": null,
                              "categories": [],
                              "contributors": [],
                              "deal": null,
                              "features": [],
                              "is_sponsored": false,
                              "metrics": {
                                "bought_past_month_count": 1000,
                                "offer_count": null,
                                "rating_count": 673,
                                "rating_distribution": null
                              },
                              "parent_asin": null,
                              "rank": null,
                              "rating": 4.9,
                              "ships_from": null,
                              "variants": []
                            }
                          },
                          "price": 19.97,
                          "seller": null,
                          "shipping": {
                            "fee": null,
                            "is_offered": null
                          },
                          "thumbnail_url": "https://m.media-amazon.com/images/I/61rw2e+AtUL._AC_UY654_FMwebp_QL65_.jpg",
                          "title": "Wireless Earbuds, 2026 Bluetooth 5.4 Headphones Bass Stereo Ear Buds with Noise Cancelling Mic, LED Display in Ear Earphones 50H Playtime Ear Buds, IP7 Waterproof for Laptop Pad Phones Soft White",
                          "type": "product",
                          "unknown_fields": [
                            "media",
                            "attributes",
                            "platform_specific.amazon.contributors"
                          ],
                          "url": "https://www.amazon.com/dp/B0H8NFRF3S"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.amazon.rating",
                            "platform_specific.amazon.metrics.bought_past_month_count"
                          ],
                          "attributes": [],
                          "availability": null,
                          "category": null,
                          "category_id": null,
                          "condition": null,
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "B0FQFB8FMG",
                          "max_price": null,
                          "media": [],
                          "original_price": 249,
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "availability_label": null,
                              "best_sellers_ranks": [],
                              "brand": null,
                              "categories": [],
                              "contributors": [],
                              "deal": null,
                              "features": [],
                              "is_sponsored": false,
                              "metrics": {
                                "bought_past_month_count": 10000,
                                "offer_count": null,
                                "rating_count": 17730,
                                "rating_distribution": null
                              },
                              "parent_asin": null,
                              "rank": null,
                              "rating": 4.4,
                              "ships_from": null,
                              "variants": []
                            }
                          },
                          "price": 199,
                          "seller": null,
                          "shipping": {
                            "fee": null,
                            "is_offered": null
                          },
                          "thumbnail_url": "https://m.media-amazon.com/images/I/61solmQSSlL._AC_UY654_FMwebp_QL65_.jpg",
                          "title": "Apple AirPods Pro 3 Wireless Earbuds with Active Noise Cancellation",
                          "type": "product",
                          "unknown_fields": [
                            "media",
                            "attributes",
                            "platform_specific.amazon.contributors"
                          ],
                          "url": "https://www.amazon.com/dp/B0FQFB8FMG"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.amazon.rating"
                          ],
                          "attributes": [],
                          "availability": null,
                          "category": null,
                          "category_id": null,
                          "condition": null,
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "B0HKS3S2XJ",
                          "max_price": null,
                          "media": [],
                          "original_price": 249.99,
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "availability_label": null,
                              "best_sellers_ranks": [],
                              "brand": null,
                              "categories": [],
                              "contributors": [],
                              "deal": null,
                              "features": [],
                              "is_sponsored": false,
                              "metrics": {
                                "bought_past_month_count": null,
                                "offer_count": null,
                                "rating_count": 363,
                                "rating_distribution": null
                              },
                              "parent_asin": null,
                              "rank": null,
                              "rating": 4.7,
                              "ships_from": null,
                              "variants": []
                            }
                          },
                          "price": 19.99,
                          "seller": null,
                          "shipping": {
                            "fee": null,
                            "is_offered": null
                          },
                          "thumbnail_url": "https://m.media-amazon.com/images/I/61D5ZCSIymL._AC_UY654_FMwebp_QL65_.jpg",
                          "title": "Wireless Earbuds, Bluetooth 6.0 Headphones HiFi Stereo 50H Playback LED Digital Display Ear Buds with ENC Noise Canceling Headset, IPX7 Waterproof Earphones for Gym/Running/Work(Black)",
                          "type": "product",
                          "unknown_fields": [
                            "media",
                            "attributes",
                            "platform_specific.amazon.contributors"
                          ],
                          "url": "https://www.amazon.com/dp/B0HKS3S2XJ"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "amazon",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/AmazonSearch_productsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Products by keyword with price, rating and sales",
        "tags": [
          "Amazon"
        ],
        "x-socialtap-endpoint": "amazon.search_products",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Amazon's Featured order, sponsored results among them",
          "orders": {
            "newest": "Amazon's Newest Arrivals: the most recently listed first",
            "popular": "Amazon's Best Sellers order: the most bought first",
            "price_asc": "the lowest price first",
            "price_desc": "the highest price first",
            "relevance": "Amazon's Featured order, sponsored results among them"
          },
          "page_max": 60,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "product",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/amazon/seller": {
      "get": {
        "description": "Returns an Amazon third-party seller from its merchant ID or seller page link, on any Amazon marketplace. You get its name, logo and About text, its positive feedback share, and its star rating with exact rating counts per star for the last month, three months, year and lifetime. It also has the business details the seller must disclose: legal name, address, phone, email, and VAT and trade register numbers where shown.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/amazon/seller/ (Markdown: https://socialtap.dev/docs/reference/amazon/seller/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/amazon/seller/index.md)",
          "url": "https://socialtap.dev/docs/reference/amazon/seller/"
        },
        "operationId": "amazon.seller.get",
        "parameters": [
          {
            "description": "The seller: its merchant ID (A3A7XJ7DLGM1CB, the seller= in its links) or its link on any Amazon marketplace: its page (amazon.com/sp?seller=…), the older /gp/aag/main?seller=, /gp/help/seller/at-a-glance.html?seller= and /shops/… links, or its storefront (amazon.com/s?me=…, /sp/redirect/storefront?seller=…). Sellers have no username.",
            "example": "https://www.amazon.com/sp?seller=AN8LN2YPKS7DF",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The seller: its merchant ID (A3A7XJ7DLGM1CB, the seller= in its links) or its link on any Amazon marketplace: its page (amazon.com/sp?seller=…), the older /gp/aag/main?seller=, /gp/help/seller/at-a-glance.html?seller= and /shops/… links, or its storefront (amazon.com/s?me=…, /sp/redirect/storefront?seller=…). Sellers have no username.",
              "examples": [
                "AN8LN2YPKS7DF"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to read, by country: US (amazon.com), GB (amazon.co.uk), DE, JP, IN, … A seller's ratings and details are that marketplace's. Default: the link's marketplace, else US.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to read, by country: US (amazon.com), GB (amazon.co.uk), DE, JP, IN, … A seller's ratings and details are that marketplace's. Default: the link's marketplace, else US.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "platform_specific.amazon.seller_feedback.positive_percent",
                          "platform_specific.amazon.seller_feedback.last_30_days.rating",
                          "platform_specific.amazon.seller_feedback.last_90_days.rating"
                        ],
                        "avatar_url": "https://m.media-amazon.com/images/I/31M25Gjck3L.jpg",
                        "banner_url": null,
                        "bio": "Due to Datavision's longstanding relationships with all major manufacturers we are able to offer a broader selection of products than even the largest online retailer.\n\nDatavision is also an Authorized Retailer for all major manufacturers including Apple, Sony, SONOS, Dyson, Sams…",
                        "category": null,
                        "country_code": "US",
                        "created_at": null,
                        "display_name": "DataVision Computer Video",
                        "external_links": [],
                        "id": "AN8LN2YPKS7DF",
                        "is_private": false,
                        "is_verified": null,
                        "location": "55 W 39th Street, NEW YORK, NY, 10018, US",
                        "metrics": {
                          "follower_count": null,
                          "following_count": null,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "amazon",
                        "platform_specific": {
                          "amazon": {
                            "seller_business": {
                              "address": "55 W 39th Street, NEW YORK, NY, 10018, US",
                              "business_type": null,
                              "customer_service_address": null,
                              "customer_service_phone": "888-888-2087",
                              "email": null,
                              "legal_name": "DataVision Computer Video, Inc.",
                              "phone": null,
                              "trade_register_number": null,
                              "vat_number": null
                            },
                            "seller_feedback": {
                              "last_12_months": {
                                "rating": 4.1,
                                "rating_count": 178,
                                "rating_distribution": {
                                  "five_star_count": 128,
                                  "four_star_count": 9,
                                  "one_star_count": 36,
                                  "three_star_count": 2,
                                  "two_star_count": 3
                                },
                                "review_count": 178
                              },
                              "last_30_days": {
                                "rating": 2.7,
                                "rating_count": 12,
                                "rating_distribution": {
                                  "five_star_count": 5,
                                  "four_star_count": 0,
                                  "one_star_count": 7,
                                  "three_star_count": 0,
                                  "two_star_count": 0
                                },
                                "review_count": 12
                              },
                              "last_90_days": {
                                "rating": 3.7,
                                "rating_count": 36,
                                "rating_distribution": {
                                  "five_star_count": 22,
                                  "four_star_count": 3,
                                  "one_star_count": 11,
                                  "three_star_count": 0,
                                  "two_star_count": 0
                                },
                                "review_count": 36
                              },
                              "lifetime": {
                                "rating": 4.7,
                                "rating_count": 144093,
                                "rating_distribution": {
                                  "five_star_count": 123370,
                                  "four_star_count": 11762,
                                  "one_star_count": 4515,
                                  "three_star_count": 2784,
                                  "two_star_count": 1662
                                },
                                "review_count": 144086
                              },
                              "positive_percent": 77
                            },
                            "shop": null
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://www.amazon.com/sp?seller=AN8LN2YPKS7DF",
                        "username": null
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "amazon",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "AN8LN2YPKS7DF",
                          "url": "https://www.amazon.com/sp?seller=AN8LN2YPKS7DF"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/AmazonSellerResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Seller ratings, feedback counts and business details",
        "tags": [
          "Amazon"
        ],
        "x-socialtap-endpoint": "amazon.seller",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/amazon/shop": {
      "get": {
        "description": "Returns an Amazon influencer's storefront from its handle or amazon.com/shop link, on any Amazon marketplace. You get the creator's name, picture, bio, social links and account ID, whether Amazon marks it a Top Creator, its curations with their post counts, and the products it shows as trending with their prices. Its idea lists, a page at a time, come from the Amazon Shop Lists API.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/amazon/shop/ (Markdown: https://socialtap.dev/docs/reference/amazon/shop/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/amazon/shop/index.md)",
          "url": "https://socialtap.dev/docs/reference/amazon/shop/"
        },
        "operationId": "amazon.shop.get",
        "parameters": [
          {
            "description": "The influencer's storefront: its handle (sydneydelrey, the name after /shop/ in its link, any case, with or without the @), its link on any Amazon marketplace (amazon.com/shop/sydneydelrey, or a link to one of its photos, videos or curations), or its account ID (amzn1.account.…, the id this API returns) or amazon.com/gp/profile/ link.",
            "example": "sydneydelrey",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The influencer's storefront: its handle (sydneydelrey, the name after /shop/ in its link, any case, with or without the @), its link on any Amazon marketplace (amazon.com/shop/sydneydelrey, or a link to one of its photos, videos or curations), or its account ID (amzn1.account.…, the id this API returns) or amazon.com/gp/profile/ link.",
              "examples": [
                "sydneydelrey"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to read, by country: US (amazon.com), GB (amazon.co.uk), DE, CA, IN, … A storefront shows that marketplace's prices; Amazon shows a creator's storefront on other marketplaces too. Default: the link's marketplace, else US.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to read, by country: US (amazon.com), GB (amazon.co.uk), DE, CA, IN, … A storefront shows that marketplace's prices; Amazon shows a creator's storefront on other marketplaces too. Default: the link's marketplace, else US.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://m.media-amazon.com/images/I/71D+tmgGHHL._CR0%2C0%2C972%2C972_.jpg",
                        "banner_url": null,
                        "bio": "sharing all of my favorite Amazon finds ᥫ᭡ click the icons below to follow me on socials! all photo & video content is also shoppable x",
                        "category": null,
                        "country_code": null,
                        "created_at": null,
                        "display_name": "sydney del rey",
                        "external_links": [
                          {
                            "title": "TIKTOK",
                            "url": "https://vm.tiktok.com/ZTFrowSpg/"
                          },
                          {
                            "title": "YOUTUBE",
                            "url": "https://www.youtube.com/channel/UCWvW1JOQ-nsAinO1jLFgrVA"
                          },
                          {
                            "title": "PINTEREST",
                            "url": "https://www.pinterest.com/sydneydelrey"
                          }
                        ],
                        "id": "amzn1.account.AFLEV5XW2UDKGVOLTFVTZTVW3ZDQ",
                        "is_private": false,
                        "is_verified": null,
                        "location": null,
                        "metrics": {
                          "follower_count": null,
                          "following_count": null,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "amazon",
                        "platform_specific": {
                          "amazon": {
                            "seller_business": null,
                            "seller_feedback": null,
                            "shop": {
                              "curations": [
                                {
                                  "id": "bdca11e0-6920-4402-ac72-2f2016ed1e36",
                                  "post_count": 14,
                                  "thumbnail_url": "https://m.media-amazon.com/images/I/41hpqw-D5tL._US225_SCLZZZZZZZ_.jpg",
                                  "title": "SHOES ✨",
                                  "url": "https://www.amazon.com/shop/sydneydelrey/curation/bdca11e0-6920-4402-ac72-2f2016ed1e36"
                                },
                                {
                                  "id": "71fad634-5787-4ee1-bc3c-6e3ca23e5eae",
                                  "post_count": 109,
                                  "thumbnail_url": "https://m.media-amazon.com/images/S/shoppable-media-external-prod-iad-us-east-1/8d48ee6a-0c49-4441-b385-a50fb9d86618/3254e-2233-46c9-89bd-434412530._SX225_SCLZZZZZZZ_.jpeg",
                                  "title": "f/w fit try ons",
                                  "url": "https://www.amazon.com/shop/sydneydelrey/curation/71fad634-5787-4ee1-bc3c-6e3ca23e5eae"
                                },
                                {
                                  "id": "7e16f5d6-99a7-4277-b498-caffddd25cd5",
                                  "post_count": 12,
                                  "thumbnail_url": "https://m.media-amazon.com/images/I/41gq2G5kbDL._US225_SCLZZZZZZZ_.jpg",
                                  "title": "fall by category 🍂",
                                  "url": "https://www.amazon.com/shop/sydneydelrey/curation/7e16f5d6-99a7-4277-b498-caffddd25cd5"
                                }
                              ],
                              "is_top_creator": true,
                              "trending_picks": [
                                {
                                  "asin": "B0HCMQP824",
                                  "badge": "Deal",
                                  "currency": "USD",
                                  "image_url": "https://m.media-amazon.com/images/I/41HROkFYKfL._AC_.jpg",
                                  "price": 15.29,
                                  "url": "https://www.amazon.com/dp/B0HCMQP824"
                                },
                                {
                                  "asin": "B0H9QNCXRZ",
                                  "badge": "Deal",
                                  "currency": "USD",
                                  "image_url": "https://m.media-amazon.com/images/I/31i0y9mO5GL._AC_.jpg",
                                  "price": 19.94,
                                  "url": "https://www.amazon.com/dp/B0H9QNCXRZ"
                                },
                                {
                                  "asin": "B0H2CSDFJJ",
                                  "badge": "Deal",
                                  "currency": "USD",
                                  "image_url": "https://m.media-amazon.com/images/I/415s0nFsMDL._AC_.jpg",
                                  "price": 13.99,
                                  "url": "https://www.amazon.com/dp/B0H2CSDFJJ"
                                }
                              ]
                            }
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://www.amazon.com/shop/sydneydelrey",
                        "username": "sydneydelrey"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "amazon",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "amzn1.account.AFLEV5XW2UDKGVOLTFVTZTVW3ZDQ",
                          "url": "https://www.amazon.com/shop/sydneydelrey"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/AmazonShopResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Influencer storefront profiles, curations and picks",
        "tags": [
          "Amazon"
        ],
        "x-socialtap-endpoint": "amazon.shop",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/amazon/shop_lists": {
      "get": {
        "description": "Returns an Amazon influencer's idea lists from its storefront handle or amazon.com/shop link, on any Amazon marketplace. Each list has its title, link, cover image, product count, exact heart count, whether it is pinned, and the ASINs of its first products. Lists come newest first, a page at a time, and the list pages on.\n\nReturns `{data, page, meta}`: `data` holds up to 20 `Playlist` items (the shared schema, the same on every platform), the storefront's order: the list created or changed most recently first, with the lists the influencer pinned at the top of the first page. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/amazon/shop_lists/ (Markdown: https://socialtap.dev/docs/reference/amazon/shop_lists/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/amazon/shop_lists/index.md)",
          "url": "https://socialtap.dev/docs/reference/amazon/shop_lists/"
        },
        "operationId": "amazon.shop_lists.list",
        "parameters": [
          {
            "description": "The influencer's storefront: its handle (sydneydelrey, the name after /shop/ in its link, any case, with or without the @), its link on any Amazon marketplace (amazon.com/shop/sydneydelrey, or a link to one of its photos, videos or curations), or its account ID (amzn1.account.…, the id the Amazon Shop API returns) or amazon.com/gp/profile/ link.",
            "example": "sydneydelrey",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The influencer's storefront: its handle (sydneydelrey, the name after /shop/ in its link, any case, with or without the @), its link on any Amazon marketplace (amazon.com/shop/sydneydelrey, or a link to one of its photos, videos or curations), or its account ID (amzn1.account.…, the id the Amazon Shop API returns) or amazon.com/gp/profile/ link.",
              "examples": [
                "sydneydelrey"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to read, by country: US (amazon.com), GB (amazon.co.uk), DE, CA, IN, … A storefront shows that marketplace's prices; Amazon shows a creator's storefront on other marketplaces too. Default: the link's marketplace, else US.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to read, by country: US (amazon.com), GB (amazon.co.uk), DE, CA, IN, … A storefront shows that marketplace's prices; Amazon shows a creator's storefront on other marketplaces too. Default: the link's marketplace, else US.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 20,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "platform_specific.amazon.products"
                          ],
                          "description": null,
                          "id": "XYAIGEFWJGML",
                          "is_collaborative": null,
                          "metrics": {
                            "post_count": null
                          },
                          "owner": {
                            "avatar_url": null,
                            "display_name": null,
                            "id": null,
                            "is_verified": null,
                            "url": "https://www.amazon.com/shop/sydneydelrey",
                            "username": "sydneydelrey"
                          },
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "heart_count": 27,
                              "is_pinned": true,
                              "product_count": 107,
                              "products": [
                                {
                                  "asin": "B0GVJLT11G",
                                  "image_url": "https://m.media-amazon.com/images/I/51rkpKJTMSL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0GVJLT11G"
                                },
                                {
                                  "asin": "B0CBV78KG1",
                                  "image_url": "https://m.media-amazon.com/images/I/3116aEzGVvL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0CBV78KG1"
                                },
                                {
                                  "asin": "B0FDWQ3B2D",
                                  "image_url": "https://m.media-amazon.com/images/I/51XQoZ399aL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0FDWQ3B2D"
                                }
                              ]
                            }
                          },
                          "platform_type": "idea list",
                          "thumbnail_url": "https://m.media-amazon.com/images/I/8153xDsodTL._AC_._US550_SCLZZZZZZZ_.jpg",
                          "title": "Holiday home goods",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://www.amazon.com/shop/sydneydelrey/list/XYAIGEFWJGML"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.amazon.products"
                          ],
                          "description": null,
                          "id": "35KWG9X334D4Q",
                          "is_collaborative": null,
                          "metrics": {
                            "post_count": null
                          },
                          "owner": {
                            "avatar_url": null,
                            "display_name": null,
                            "id": null,
                            "is_verified": null,
                            "url": "https://www.amazon.com/shop/sydneydelrey",
                            "username": "sydneydelrey"
                          },
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "heart_count": 203,
                              "is_pinned": true,
                              "product_count": 199,
                              "products": [
                                {
                                  "asin": "B0H8Y7QSW1",
                                  "image_url": "https://m.media-amazon.com/images/I/41MHUWP3IbL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0H8Y7QSW1"
                                },
                                {
                                  "asin": "B0GPL62DKQ",
                                  "image_url": "https://m.media-amazon.com/images/I/31pmcuxsQHL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0GPL62DKQ"
                                },
                                {
                                  "asin": "B0F1K1KF8Q",
                                  "image_url": "https://m.media-amazon.com/images/I/418Krr3QwqL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0F1K1KF8Q"
                                }
                              ]
                            }
                          },
                          "platform_type": "idea list",
                          "thumbnail_url": "https://m.media-amazon.com/images/I/81uZzOaydpL._AC_._US550_SCLZZZZZZZ_.jpg",
                          "title": "thanksgiving fitspo",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://www.amazon.com/shop/sydneydelrey/list/35KWG9X334D4Q"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.amazon.products"
                          ],
                          "description": null,
                          "id": "3C0MB7YWND2K7",
                          "is_collaborative": null,
                          "metrics": {
                            "post_count": null
                          },
                          "owner": {
                            "avatar_url": null,
                            "display_name": null,
                            "id": null,
                            "is_verified": null,
                            "url": "https://www.amazon.com/shop/sydneydelrey",
                            "username": "sydneydelrey"
                          },
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "heart_count": 501,
                              "is_pinned": true,
                              "product_count": 59,
                              "products": [
                                {
                                  "asin": "B0F4CSXK79",
                                  "image_url": "https://m.media-amazon.com/images/I/41SaX31kWLL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0F4CSXK79"
                                },
                                {
                                  "asin": "B0GXYS8B3N",
                                  "image_url": "https://m.media-amazon.com/images/I/215DmLHX1wL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0GXYS8B3N"
                                },
                                {
                                  "asin": "B0C5R54TMC",
                                  "image_url": "https://m.media-amazon.com/images/I/41eoI7oRyiL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0C5R54TMC"
                                }
                              ]
                            }
                          },
                          "platform_type": "idea list",
                          "thumbnail_url": "https://m.media-amazon.com/images/I/71noBGE95aL._AC_._US550_SCLZZZZZZZ_.jpg",
                          "title": "my amazon boot collection",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://www.amazon.com/shop/sydneydelrey/list/3C0MB7YWND2K7"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "amazon",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": null,
                          "url": "https://www.amazon.com/shop/sydneydelrey"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/AmazonShop_listsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Influencer idea lists with product counts and products",
        "tags": [
          "Amazon"
        ],
        "x-socialtap-endpoint": "amazon.shop_lists",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the storefront's order: the list created or changed most recently first, with the lists the influencer pinned at the top of the first page",
          "page_max": 20,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "playlist",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/amazon/shop_posts": {
      "get": {
        "description": "Returns an Amazon influencer's storefront videos and shoppable photos from its handle or amazon.com/shop link, on any Amazon marketplace. Each post has its link, image, exact heart count, whether it is pinned, and the ASINs of the products it tags; videos add their title, length, stream and captions. Posts come a page at a time, and the list pages on.\n\nReturns `{data, page, meta}`: `data` holds up to 20 `Post` items (the shared schema, the same on every platform), the storefront's: newest first within each tab, after the posts the influencer pinned; type=all lists the videos, then the photos. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Amazon's words: `metrics.like_count` is hearts.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/amazon/shop_posts/ (Markdown: https://socialtap.dev/docs/reference/amazon/shop_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/amazon/shop_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/amazon/shop_posts/"
        },
        "operationId": "amazon.shop_posts.list",
        "parameters": [
          {
            "description": "The influencer's storefront: its handle (sydneydelrey, the name after /shop/ in its link, any case, with or without the @) or its link on any Amazon marketplace (amazon.com/shop/sydneydelrey, or a link to one of its photos, videos or lists), or its account ID (amzn1.account.…, the id the Amazon Shop API returns) or amazon.com/gp/profile/ link.",
            "example": "sydneydelrey",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The influencer's storefront: its handle (sydneydelrey, the name after /shop/ in its link, any case, with or without the @) or its link on any Amazon marketplace (amazon.com/shop/sydneydelrey, or a link to one of its photos, videos or lists), or its account ID (amzn1.account.…, the id the Amazon Shop API returns) or amazon.com/gp/profile/ link.",
              "examples": [
                "sydneydelrey"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to read, by country: US (amazon.com), GB (amazon.co.uk), DE, CA, IN, … Amazon shows a creator's storefront on other marketplaces too. Default: the link's marketplace, else US.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace to read, by country: US (amazon.com), GB (amazon.co.uk), DE, CA, IN, … Amazon shows a creator's storefront on other marketplaces too. Default: the link's marketplace, else US.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Which posts: all (default: the videos, then the photos), video (the Videos tab) or photo (the Photos tab). Each comes newest first, after the ones the influencer pinned.",
            "example": "video",
            "in": "query",
            "name": "type",
            "schema": {
              "default": "all",
              "description": "Which posts: all (default: the videos, then the photos), video (the Videos tab) or photo (the Photos tab). Each comes newest first, after the ones the influencer pinned.",
              "enum": [
                "all",
                "video",
                "photo"
              ],
              "examples": [
                "video"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 20,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "duration_ms",
                            "media[].duration_ms"
                          ],
                          "author": {
                            "avatar_url": null,
                            "display_name": "sydney del rey",
                            "id": null,
                            "is_verified": null,
                            "url": "https://www.amazon.com/shop/sydneydelrey",
                            "username": "sydneydelrey"
                          },
                          "coauthors": [],
                          "duration_ms": 13000,
                          "hashtags": [],
                          "id": "amzn1.vse.video.06f941e7892544b88b70d6dceccb9f75",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 13000,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://m.media-amazon.com/images/I/71zBDXAfzuL.jpg",
                              "type": "video",
                              "url": "https://m.media-amazon.com/images/S/vse-vms-transcoding-artifact-us-east-1-prod/3f39ab0a-1c38-4793-95e8-84e0ac36cb89/default.vertical.jobtemplate.hls.m3u8",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 3,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "caption_tracks": [
                                {
                                  "language": "en",
                                  "url": "https://m.media-amazon.com/images/S/vse-vms-closed-captions-artifact-us-east-1-prod/closedCaptions/914c778f-c109-4c59-a938-9490a69df65b.vtt"
                                }
                              ],
                              "products": [
                                {
                                  "asin": "B0H1KZ971L",
                                  "image_url": "https://m.media-amazon.com/images/I/31eFzhWptZL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0H1KZ971L"
                                }
                              ]
                            }
                          },
                          "platform_type": "video",
                          "published_at": null,
                          "text": null,
                          "thumbnail_url": "https://m.media-amazon.com/images/I/71zBDXAfzuL.jpg",
                          "title": "Cutest fall shoes",
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.amazon.com/shop/sydneydelrey/video/amzn1.vse.video.06f941e7892544b88b70d6dceccb9f75"
                        },
                        {
                          "approximate_fields": [
                            "duration_ms",
                            "media[].duration_ms"
                          ],
                          "author": {
                            "avatar_url": null,
                            "display_name": "sydney del rey",
                            "id": null,
                            "is_verified": null,
                            "url": "https://www.amazon.com/shop/sydneydelrey",
                            "username": "sydneydelrey"
                          },
                          "coauthors": [],
                          "duration_ms": 12000,
                          "hashtags": [],
                          "id": "amzn1.vse.video.0268c2451115439da062daabeeeaa5c3",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 12000,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://m.media-amazon.com/images/I/B1wSa5vdPsL.jpg",
                              "type": "video",
                              "url": "https://m.media-amazon.com/images/S/vse-vms-transcoding-artifact-us-east-1-prod/ffa8185f-135a-43e3-9c06-2ee586932bf2/default.vertical.jobtemplate.hls.m3u8",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 4,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "caption_tracks": [
                                {
                                  "language": "en",
                                  "url": "https://m.media-amazon.com/images/S/vse-vms-closed-captions-artifact-us-east-1-prod/closedCaptions/a4105c6b-ff9c-4c3d-8de0-40979387ba53.vtt"
                                }
                              ],
                              "products": [
                                {
                                  "asin": "B0GXYZZQV7",
                                  "image_url": "https://m.media-amazon.com/images/I/215DmLHX1wL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0GXYZZQV7"
                                },
                                {
                                  "asin": "B0C5R54TMC",
                                  "image_url": "https://m.media-amazon.com/images/I/41eoI7oRyiL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0C5R54TMC"
                                },
                                {
                                  "asin": "B0FL26334T",
                                  "image_url": "https://m.media-amazon.com/images/I/31QTHBsDpqL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0FL26334T"
                                }
                              ]
                            }
                          },
                          "platform_type": "video",
                          "published_at": null,
                          "text": null,
                          "thumbnail_url": "https://m.media-amazon.com/images/I/B1wSa5vdPsL.jpg",
                          "title": "Knee high boots I loveee",
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.amazon.com/shop/sydneydelrey/video/amzn1.vse.video.0268c2451115439da062daabeeeaa5c3"
                        },
                        {
                          "approximate_fields": [
                            "duration_ms",
                            "media[].duration_ms"
                          ],
                          "author": {
                            "avatar_url": null,
                            "display_name": "sydney del rey",
                            "id": null,
                            "is_verified": null,
                            "url": "https://www.amazon.com/shop/sydneydelrey",
                            "username": "sydneydelrey"
                          },
                          "coauthors": [],
                          "duration_ms": 15000,
                          "hashtags": [],
                          "id": "amzn1.vse.video.0c05663ba13d416e9312c6d750ed8cac",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 15000,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://m.media-amazon.com/images/I/71F4pVkSj7L.jpg",
                              "type": "video",
                              "url": "https://m.media-amazon.com/images/S/vse-vms-transcoding-artifact-us-east-1-prod/fc109474-4e87-4722-855c-0b782c25f91f/default.vertical.jobtemplate.hls.m3u8",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 3,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "caption_tracks": [
                                {
                                  "language": "en",
                                  "url": "https://m.media-amazon.com/images/S/vse-vms-closed-captions-artifact-us-east-1-prod/closedCaptions/cb17c115-bb41-470e-a684-d2f6b7fbdd0d.vtt"
                                }
                              ],
                              "products": [
                                {
                                  "asin": "B0HBQPNWGF",
                                  "image_url": "https://m.media-amazon.com/images/I/41DxBh9NtVL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0HBQPNWGF"
                                },
                                {
                                  "asin": "B0G3PNFZNS",
                                  "image_url": "https://m.media-amazon.com/images/I/41g8qPygidL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0G3PNFZNS"
                                },
                                {
                                  "asin": "B0HJQXL7WZ",
                                  "image_url": "https://m.media-amazon.com/images/I/41493s3kcgL._AC_.jpg",
                                  "url": "https://www.amazon.com/dp/B0HJQXL7WZ"
                                }
                              ]
                            }
                          },
                          "platform_type": "video",
                          "published_at": null,
                          "text": null,
                          "thumbnail_url": "https://m.media-amazon.com/images/I/71F4pVkSj7L.jpg",
                          "title": "New fall tops you'll love!",
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.amazon.com/shop/sydneydelrey/video/amzn1.vse.video.0c05663ba13d416e9312c6d750ed8cac"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "amazon",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": null,
                          "url": "https://www.amazon.com/shop/sydneydelrey"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/AmazonShop_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Influencer storefront videos and photos with tagged products",
        "tags": [
          "Amazon"
        ],
        "x-socialtap-endpoint": "amazon.shop_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the storefront's: newest first within each tab, after the posts the influencer pinned; type=all lists the videos, then the photos",
          "page_max": 20,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/amazon/top_products": {
      "get": {
        "description": "Returns Amazon's Best Sellers of a category, ranked from the top, from its department, browse node or Best Sellers link, on any Amazon marketplace. Each product has its rank, ASIN, title, image, current price, star rating and exact rating count, and a book's author. The same category's New Releases come back the same way.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Product` items (the shared schema, the same on every platform), Amazon's rank in the list (1 = top). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/amazon/top_products/ (Markdown: https://socialtap.dev/docs/reference/amazon/top_products/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/amazon/top_products/index.md)",
          "url": "https://socialtap.dev/docs/reference/amazon/top_products/"
        },
        "operationId": "amazon.top_products.list",
        "parameters": [
          {
            "description": "The category: its department's slug as Amazon's Best Sellers links write it (electronics, books, or ce-de on Amazon Germany), optionally with a browse node after a slash (electronics/12097478011), the browse node alone (12097478011), or the list's link itself (amazon.com/gp/bestsellers/electronics/12097478011, a /zgbs/ link, or a New Releases, Movers & Shakers, Most Wished For or Gift Ideas link). A product's platform_specific.amazon.best_sellers_ranks[].category_id is one of these.",
            "example": "electronics",
            "in": "query",
            "name": "category",
            "required": true,
            "schema": {
              "description": "The category: its department's slug as Amazon's Best Sellers links write it (electronics, books, or ce-de on Amazon Germany), optionally with a browse node after a slash (electronics/12097478011), the browse node alone (12097478011), or the list's link itself (amazon.com/gp/bestsellers/electronics/12097478011, a /zgbs/ link, or a New Releases, Movers & Shakers, Most Wished For or Gift Ideas link). A product's platform_specific.amazon.best_sellers_ranks[].category_id is one of these.",
              "examples": [
                "electronics"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Which of the category's lists: best_sellers (the most sold), new_releases (the best-selling new and upcoming products), movers_and_shakers (the biggest sales rank gains in a day), most_wished_for (the most added to wish lists) or gift_ideas (the most bought as gifts). Amazon shows no products in the last three today. Default: the link's list, else best_sellers.",
            "example": "new_releases",
            "in": "query",
            "name": "list",
            "schema": {
              "description": "Which of the category's lists: best_sellers (the most sold), new_releases (the best-selling new and upcoming products), movers_and_shakers (the biggest sales rank gains in a day), most_wished_for (the most added to wish lists) or gift_ideas (the most bought as gifts). Amazon shows no products in the last three today. Default: the link's list, else best_sellers.",
              "enum": [
                "best_sellers",
                "new_releases",
                "movers_and_shakers",
                "most_wished_for",
                "gift_ideas"
              ],
              "examples": [
                "new_releases"
              ],
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace whose list to read, by country: US (amazon.com), GB (amazon.co.uk), DE, JP, IN, … Departments and their slugs are each marketplace's own. Default: the link's marketplace, else US.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Amazon marketplace whose list to read, by country: US (amazon.com), GB (amazon.co.uk), DE, JP, IN, … Departments and their slugs are each marketplace's own. Default: the link's marketplace, else US.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "platform_specific.amazon.rating"
                          ],
                          "attributes": [],
                          "availability": null,
                          "category": null,
                          "category_id": null,
                          "condition": null,
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "B08JHCVHTY",
                          "max_price": null,
                          "media": [],
                          "original_price": null,
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "availability_label": null,
                              "best_sellers_ranks": [],
                              "brand": null,
                              "categories": [],
                              "contributors": [],
                              "deal": null,
                              "features": [],
                              "is_sponsored": null,
                              "metrics": {
                                "bought_past_month_count": null,
                                "offer_count": null,
                                "rating_count": 281899,
                                "rating_distribution": null
                              },
                              "parent_asin": null,
                              "rank": 1,
                              "rating": 4.4,
                              "ships_from": null,
                              "variants": []
                            }
                          },
                          "price": 11.99,
                          "seller": null,
                          "shipping": {
                            "fee": null,
                            "is_offered": null
                          },
                          "thumbnail_url": "https://images-na.ssl-images-amazon.com/images/I/31YHGbJsldL._AC_UL900_SR900,600_.png",
                          "title": "blink plus plan with monthly auto-renewal",
                          "type": "product",
                          "unknown_fields": [
                            "media",
                            "attributes",
                            "platform_specific.amazon.contributors"
                          ],
                          "url": "https://www.amazon.com/dp/B08JHCVHTY"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.amazon.rating"
                          ],
                          "attributes": [],
                          "availability": null,
                          "category": null,
                          "category_id": null,
                          "condition": null,
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "B0DCH8VDXF",
                          "max_price": null,
                          "media": [],
                          "original_price": null,
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "availability_label": null,
                              "best_sellers_ranks": [],
                              "brand": null,
                              "categories": [],
                              "contributors": [],
                              "deal": null,
                              "features": [],
                              "is_sponsored": null,
                              "metrics": {
                                "bought_past_month_count": null,
                                "offer_count": null,
                                "rating_count": 20075,
                                "rating_distribution": null
                              },
                              "parent_asin": null,
                              "rank": 2,
                              "rating": 4.5,
                              "ships_from": null,
                              "variants": []
                            }
                          },
                          "price": 19,
                          "seller": null,
                          "shipping": {
                            "fee": null,
                            "is_offered": null
                          },
                          "thumbnail_url": "https://images-na.ssl-images-amazon.com/images/I/513OSdW4elL._AC_UL900_SR900,600_.jpg",
                          "title": "Apple EarPods Headphones with USB-C Plug, Wired Ear Buds with Built-in Remote to Control Music, Phone Calls, and Volume",
                          "type": "product",
                          "unknown_fields": [
                            "media",
                            "attributes",
                            "platform_specific.amazon.contributors"
                          ],
                          "url": "https://www.amazon.com/dp/B0DCH8VDXF"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.amazon.rating"
                          ],
                          "attributes": [],
                          "availability": null,
                          "category": null,
                          "category_id": null,
                          "condition": null,
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "B0GJTFXNRX",
                          "max_price": null,
                          "media": [],
                          "original_price": null,
                          "platform": "amazon",
                          "platform_specific": {
                            "amazon": {
                              "availability_label": null,
                              "best_sellers_ranks": [],
                              "brand": null,
                              "categories": [],
                              "contributors": [],
                              "deal": null,
                              "features": [],
                              "is_sponsored": null,
                              "metrics": {
                                "bought_past_month_count": null,
                                "offer_count": null,
                                "rating_count": 13061,
                                "rating_distribution": null
                              },
                              "parent_asin": null,
                              "rank": 3,
                              "rating": 4.6,
                              "ships_from": null,
                              "variants": []
                            }
                          },
                          "price": 23,
                          "seller": null,
                          "shipping": {
                            "fee": null,
                            "is_offered": null
                          },
                          "thumbnail_url": "https://images-na.ssl-images-amazon.com/images/I/61Qd9Z9caRL._AC_UL900_SR900,600_.jpg",
                          "title": "Apple AirTag (2nd Generation): Tracker for Keychain, Wallet, and More; Locator with Sound; Simple One-Tap Setup with iPhone or iPad; Key Finder with up to 1.5X Precision Finding Range",
                          "type": "product",
                          "unknown_fields": [
                            "media",
                            "attributes",
                            "platform_specific.amazon.contributors"
                          ],
                          "url": "https://www.amazon.com/dp/B0GJTFXNRX"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "amazon",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/AmazonTop_productsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Top 100 products of any category, ranked",
        "tags": [
          "Amazon"
        ],
        "x-socialtap-endpoint": "amazon.top_products",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Amazon's rank in the list (1 = top)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "product",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/api_keys": {
      "get": {
        "description": "The account's keys, newest first, revoked ones included; never their secrets. Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "api_keys.list",
        "parameters": [
          {
            "description": "Keys per page (default and maximum 100).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "created_at": {
                            "description": "When the key was created, RFC 3339 UTC.",
                            "format": "date-time",
                            "type": "string"
                          },
                          "created_by_key": {
                            "description": "The API key (key_…) that last created this key, gave it the admin scope or rotated it: revoking that key also revokes this one if this one has admin. Null when none did, or a person has rotated it in the dashboard since.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "created_by_user": {
                            "description": "The person (GET /v1/members user_id) who created this key in the dashboard, or whose key created it. They may have left the account since. Null when no person did (an operator, or a key from before this was recorded).",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "dashboard": {
                            "description": "true for the account's built-in dashboard key: the dashboard's playground runs as it (so its requests are logged, counted and billed like any key's). Nobody holds its secret, so it works only from the signed-in dashboard. Only its spend_limit can be changed (to cap what the playground spends live); renaming, rescoping, restricting, rotating or revoking it is forbidden (details.reason dashboard_key). It is made on first use and revoked with the account.",
                            "type": "boolean"
                          },
                          "expires_at": {
                            "description": "When the key stops working, RFC 3339 UTC; null when it never expires.",
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "id": {
                            "description": "Key ID (key_…): manage the key with it. It is not the secret.",
                            "type": "string"
                          },
                          "ip_allowlist": {
                            "description": "IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; [] = any.",
                            "items": {
                              "type": "string"
                            },
                            "type": "array"
                          },
                          "last_used_at": {
                            "description": "About when the key was last used (updated at most hourly); null when never.",
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "name": {
                            "description": "Your label for the key.",
                            "type": "string"
                          },
                          "object": {
                            "description": "Always api_key.",
                            "enum": [
                              "api_key"
                            ],
                            "type": "string"
                          },
                          "prefix": {
                            "description": "The secret's first characters, to recognize it.",
                            "type": "string"
                          },
                          "previous_secret_expires_at": {
                            "description": "Until then the secret this key had before its last rotation works too (rotate_secret), RFC 3339 UTC; null when none does.",
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "revoked_at": {
                            "description": "When the key was revoked; null while it is not.",
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "scopes": {
                            "description": "What the key may call: endpoints (data endpoints), jobs (create, read and cancel jobs; includes jobs:read), jobs:read (read jobs and their results), account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).",
                            "items": {
                              "enum": [
                                "endpoints",
                                "jobs",
                                "jobs:read",
                                "account:read",
                                "admin"
                              ],
                              "type": "string"
                            },
                            "type": "array"
                          },
                          "spend_limit": {
                            "description": "The key's spend limit and what it used this interval; null when the key has none.",
                            "properties": {
                              "amount": {
                                "description": "Most credits the key may spend per interval.",
                                "type": "integer"
                              },
                              "interval": {
                                "description": "Calendar day or month, UTC.",
                                "enum": [
                                  "day",
                                  "month"
                                ],
                                "type": "string"
                              },
                              "resets_at": {
                                "description": "Start of the next interval, RFC 3339 UTC.",
                                "format": "date-time",
                                "type": "string"
                              },
                              "used": {
                                "description": "Credits the key spent this interval, plus what its requests in flight hold.",
                                "type": "integer"
                              }
                            },
                            "required": [
                              "amount",
                              "interval",
                              "used",
                              "resets_at"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "status": {
                            "description": "pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.",
                            "enum": [
                              "active",
                              "pending",
                              "expired",
                              "revoked"
                            ],
                            "type": "string"
                          }
                        },
                        "required": [
                          "object",
                          "id",
                          "name",
                          "status",
                          "prefix",
                          "scopes",
                          "spend_limit",
                          "expires_at",
                          "ip_allowlist",
                          "created_at",
                          "last_used_at",
                          "revoked_at",
                          "dashboard",
                          "previous_secret_expires_at",
                          "created_by_key",
                          "created_by_user"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List API keys",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "List API keys",
        "tags": [
          "API keys"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "post": {
        "description": "Creates a key with the given scopes, spend limit, expiry and IP allowlist. The secret is in this answer only: store it now. A key never gets a scope its creator lacks. Free.\n\n**Auth:** an API key with the `admin` scope, or the dashboard session.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "api_keys.create",
        "parameters": [
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "expires_at": {
                    "description": "RFC 3339, in the future. Default: never; made with an API key, that key's expiry (never later).",
                    "format": "date-time",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "ip_allowlist": {
                    "description": "IP addresses or CIDR ranges (203.0.113.0/24, 2001:db8::/32). Default: [] (any); made with an API key, that key's allowlist (every entry within it).",
                    "items": {
                      "maxLength": 64,
                      "type": "string"
                    },
                    "maxItems": 50,
                    "type": "array"
                  },
                  "mode": {
                    "description": "live, the only mode: test mode was retired on 2026-11-09, so \"test\" is invalid_input. Every key spends credits.",
                    "enum": [
                      "live"
                    ],
                    "type": "string"
                  },
                  "name": {
                    "description": "Your label for the key. Default: \"API key\".",
                    "maxLength": 100,
                    "type": "string"
                  },
                  "scopes": {
                    "description": "Default: endpoints, jobs and account:read. Only an admin credential creates keys, and a key never gets a scope its creator lacks.",
                    "items": {
                      "enum": [
                        "endpoints",
                        "jobs",
                        "jobs:read",
                        "account:read",
                        "admin"
                      ],
                      "type": "string"
                    },
                    "maxItems": 5,
                    "minItems": 1,
                    "type": "array"
                  },
                  "spend_limit": {
                    "description": "Default: none; made with an API key, that key's own (a key never creates a looser one).",
                    "properties": {
                      "amount": {
                        "description": "Most credits the key may spend per interval; above it, requests fail with spend_limit_reached.",
                        "maximum": 1000000000,
                        "minimum": 1,
                        "type": "integer"
                      },
                      "interval": {
                        "description": "Calendar day or month, UTC.",
                        "enum": [
                          "day",
                          "month"
                        ],
                        "type": "string"
                      }
                    },
                    "required": [
                      "amount",
                      "interval"
                    ],
                    "type": [
                      "object",
                      "null"
                    ]
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "created_at": {
                          "description": "When the key was created, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "created_by_key": {
                          "description": "The API key (key_…) that last created this key, gave it the admin scope or rotated it: revoking that key also revokes this one if this one has admin. Null when none did, or a person has rotated it in the dashboard since.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "created_by_user": {
                          "description": "The person (GET /v1/members user_id) who created this key in the dashboard, or whose key created it. They may have left the account since. Null when no person did (an operator, or a key from before this was recorded).",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "dashboard": {
                          "description": "true for the account's built-in dashboard key: the dashboard's playground runs as it (so its requests are logged, counted and billed like any key's). Nobody holds its secret, so it works only from the signed-in dashboard. Only its spend_limit can be changed (to cap what the playground spends live); renaming, rescoping, restricting, rotating or revoking it is forbidden (details.reason dashboard_key). It is made on first use and revoked with the account.",
                          "type": "boolean"
                        },
                        "expires_at": {
                          "description": "When the key stops working, RFC 3339 UTC; null when it never expires.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "Key ID (key_…): manage the key with it. It is not the secret.",
                          "type": "string"
                        },
                        "ip_allowlist": {
                          "description": "IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; [] = any.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "last_used_at": {
                          "description": "About when the key was last used (updated at most hourly); null when never.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "name": {
                          "description": "Your label for the key.",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always api_key.",
                          "enum": [
                            "api_key"
                          ],
                          "type": "string"
                        },
                        "prefix": {
                          "description": "The secret's first characters, to recognize it.",
                          "type": "string"
                        },
                        "previous_secret_expires_at": {
                          "description": "Until then the secret this key had before its last rotation works too (rotate_secret), RFC 3339 UTC; null when none does.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "revoked_at": {
                          "description": "When the key was revoked; null while it is not.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "scopes": {
                          "description": "What the key may call: endpoints (data endpoints), jobs (create, read and cancel jobs; includes jobs:read), jobs:read (read jobs and their results), account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).",
                          "items": {
                            "enum": [
                              "endpoints",
                              "jobs",
                              "jobs:read",
                              "account:read",
                              "admin"
                            ],
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "secret": {
                          "description": "The key itself: send it in the x-api-key header. Shown only once: store it now.",
                          "type": "string"
                        },
                        "spend_limit": {
                          "description": "The key's spend limit and what it used this interval; null when the key has none.",
                          "properties": {
                            "amount": {
                              "description": "Most credits the key may spend per interval.",
                              "type": "integer"
                            },
                            "interval": {
                              "description": "Calendar day or month, UTC.",
                              "enum": [
                                "day",
                                "month"
                              ],
                              "type": "string"
                            },
                            "resets_at": {
                              "description": "Start of the next interval, RFC 3339 UTC.",
                              "format": "date-time",
                              "type": "string"
                            },
                            "used": {
                              "description": "Credits the key spent this interval, plus what its requests in flight hold.",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "amount",
                            "interval",
                            "used",
                            "resets_at"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "status": {
                          "description": "pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.",
                          "enum": [
                            "active",
                            "pending",
                            "expired",
                            "revoked"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "name",
                        "status",
                        "prefix",
                        "scopes",
                        "spend_limit",
                        "expires_at",
                        "ip_allowlist",
                        "created_at",
                        "last_used_at",
                        "revoked_at",
                        "dashboard",
                        "previous_secret_expires_at",
                        "created_by_key",
                        "created_by_user",
                        "secret"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Create an API key",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Create an API key",
        "tags": [
          "API keys"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/api_keys/{id}": {
      "delete": {
        "description": "Revokes a key for good (a key may revoke itself), every secret it has (during a rotation, the previous one too), and with it every key with the admin scope that this key created, gave admin or rotated, and those keys' in turn, all at once: a leaked admin key's copies don't outlive it. The answer lists them (`also_revoked`) and the keys below it without admin, which keep working (`left_standing`), as do webhook endpoints: review them after a leak. A key can't revoke a key above it, which would revoke itself: forbidden, reason revoking_own_ancestor (use the dashboard, or rotate_secret). They stop working within a minute everywhere, each with its own `api_key.revoked` event; revoking it again changes nothing. Free.\n\n**Auth:** an API key with the `admin` scope, or the dashboard session.",
        "operationId": "api_keys.revoke",
        "parameters": [
          {
            "description": "Key ID (key_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "also_revoked": {
                          "description": "The keys with the admin scope this key created, gave admin or rotated, and those keys' in turn, revoked with it.",
                          "items": {
                            "properties": {
                              "id": {
                                "description": "Key ID (key_…).",
                                "type": "string"
                              },
                              "name": {
                                "description": "Its label.",
                                "type": "string"
                              },
                              "prefix": {
                                "description": "The secret's first characters.",
                                "type": "string"
                              },
                              "scopes": {
                                "description": "What it may call.",
                                "items": {
                                  "enum": [
                                    "endpoints",
                                    "jobs",
                                    "jobs:read",
                                    "account:read",
                                    "admin"
                                  ],
                                  "type": "string"
                                },
                                "type": "array"
                              }
                            },
                            "required": [
                              "id",
                              "name",
                              "prefix",
                              "scopes"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "created_at": {
                          "description": "When the key was created, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "created_by_key": {
                          "description": "The API key (key_…) that last created this key, gave it the admin scope or rotated it: revoking that key also revokes this one if this one has admin. Null when none did, or a person has rotated it in the dashboard since.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "created_by_user": {
                          "description": "The person (GET /v1/members user_id) who created this key in the dashboard, or whose key created it. They may have left the account since. Null when no person did (an operator, or a key from before this was recorded).",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "dashboard": {
                          "description": "true for the account's built-in dashboard key: the dashboard's playground runs as it (so its requests are logged, counted and billed like any key's). Nobody holds its secret, so it works only from the signed-in dashboard. Only its spend_limit can be changed (to cap what the playground spends live); renaming, rescoping, restricting, rotating or revoking it is forbidden (details.reason dashboard_key). It is made on first use and revoked with the account.",
                          "type": "boolean"
                        },
                        "expires_at": {
                          "description": "When the key stops working, RFC 3339 UTC; null when it never expires.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "Key ID (key_…): manage the key with it. It is not the secret.",
                          "type": "string"
                        },
                        "ip_allowlist": {
                          "description": "IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; [] = any.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "last_used_at": {
                          "description": "About when the key was last used (updated at most hourly); null when never.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "left_standing": {
                          "description": "The keys without admin below it, which keep working: review them after a leak, and revoke the ones that shouldn't stay.",
                          "items": {
                            "properties": {
                              "id": {
                                "description": "Key ID (key_…).",
                                "type": "string"
                              },
                              "name": {
                                "description": "Its label.",
                                "type": "string"
                              },
                              "prefix": {
                                "description": "The secret's first characters.",
                                "type": "string"
                              },
                              "scopes": {
                                "description": "What it may call.",
                                "items": {
                                  "enum": [
                                    "endpoints",
                                    "jobs",
                                    "jobs:read",
                                    "account:read",
                                    "admin"
                                  ],
                                  "type": "string"
                                },
                                "type": "array"
                              }
                            },
                            "required": [
                              "id",
                              "name",
                              "prefix",
                              "scopes"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "name": {
                          "description": "Your label for the key.",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always api_key.",
                          "enum": [
                            "api_key"
                          ],
                          "type": "string"
                        },
                        "prefix": {
                          "description": "The secret's first characters, to recognize it.",
                          "type": "string"
                        },
                        "previous_secret_expires_at": {
                          "description": "Until then the secret this key had before its last rotation works too (rotate_secret), RFC 3339 UTC; null when none does.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "revoked_at": {
                          "description": "When the key was revoked; null while it is not.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "scopes": {
                          "description": "What the key may call: endpoints (data endpoints), jobs (create, read and cancel jobs; includes jobs:read), jobs:read (read jobs and their results), account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).",
                          "items": {
                            "enum": [
                              "endpoints",
                              "jobs",
                              "jobs:read",
                              "account:read",
                              "admin"
                            ],
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "spend_limit": {
                          "description": "The key's spend limit and what it used this interval; null when the key has none.",
                          "properties": {
                            "amount": {
                              "description": "Most credits the key may spend per interval.",
                              "type": "integer"
                            },
                            "interval": {
                              "description": "Calendar day or month, UTC.",
                              "enum": [
                                "day",
                                "month"
                              ],
                              "type": "string"
                            },
                            "resets_at": {
                              "description": "Start of the next interval, RFC 3339 UTC.",
                              "format": "date-time",
                              "type": "string"
                            },
                            "used": {
                              "description": "Credits the key spent this interval, plus what its requests in flight hold.",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "amount",
                            "interval",
                            "used",
                            "resets_at"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "status": {
                          "description": "pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.",
                          "enum": [
                            "active",
                            "pending",
                            "expired",
                            "revoked"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "name",
                        "status",
                        "prefix",
                        "scopes",
                        "spend_limit",
                        "expires_at",
                        "ip_allowlist",
                        "created_at",
                        "last_used_at",
                        "revoked_at",
                        "dashboard",
                        "previous_secret_expires_at",
                        "created_by_key",
                        "created_by_user",
                        "also_revoked",
                        "left_standing"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Revoke an API key",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Revoke an API key",
        "tags": [
          "API keys"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "get": {
        "description": "One key and its spend this interval; never its secret. Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "api_keys.get",
        "parameters": [
          {
            "description": "Key ID (key_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "created_at": {
                          "description": "When the key was created, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "created_by_key": {
                          "description": "The API key (key_…) that last created this key, gave it the admin scope or rotated it: revoking that key also revokes this one if this one has admin. Null when none did, or a person has rotated it in the dashboard since.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "created_by_user": {
                          "description": "The person (GET /v1/members user_id) who created this key in the dashboard, or whose key created it. They may have left the account since. Null when no person did (an operator, or a key from before this was recorded).",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "dashboard": {
                          "description": "true for the account's built-in dashboard key: the dashboard's playground runs as it (so its requests are logged, counted and billed like any key's). Nobody holds its secret, so it works only from the signed-in dashboard. Only its spend_limit can be changed (to cap what the playground spends live); renaming, rescoping, restricting, rotating or revoking it is forbidden (details.reason dashboard_key). It is made on first use and revoked with the account.",
                          "type": "boolean"
                        },
                        "expires_at": {
                          "description": "When the key stops working, RFC 3339 UTC; null when it never expires.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "Key ID (key_…): manage the key with it. It is not the secret.",
                          "type": "string"
                        },
                        "ip_allowlist": {
                          "description": "IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; [] = any.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "last_used_at": {
                          "description": "About when the key was last used (updated at most hourly); null when never.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "name": {
                          "description": "Your label for the key.",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always api_key.",
                          "enum": [
                            "api_key"
                          ],
                          "type": "string"
                        },
                        "prefix": {
                          "description": "The secret's first characters, to recognize it.",
                          "type": "string"
                        },
                        "previous_secret_expires_at": {
                          "description": "Until then the secret this key had before its last rotation works too (rotate_secret), RFC 3339 UTC; null when none does.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "revoked_at": {
                          "description": "When the key was revoked; null while it is not.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "scopes": {
                          "description": "What the key may call: endpoints (data endpoints), jobs (create, read and cancel jobs; includes jobs:read), jobs:read (read jobs and their results), account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).",
                          "items": {
                            "enum": [
                              "endpoints",
                              "jobs",
                              "jobs:read",
                              "account:read",
                              "admin"
                            ],
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "spend_limit": {
                          "description": "The key's spend limit and what it used this interval; null when the key has none.",
                          "properties": {
                            "amount": {
                              "description": "Most credits the key may spend per interval.",
                              "type": "integer"
                            },
                            "interval": {
                              "description": "Calendar day or month, UTC.",
                              "enum": [
                                "day",
                                "month"
                              ],
                              "type": "string"
                            },
                            "resets_at": {
                              "description": "Start of the next interval, RFC 3339 UTC.",
                              "format": "date-time",
                              "type": "string"
                            },
                            "used": {
                              "description": "Credits the key spent this interval, plus what its requests in flight hold.",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "amount",
                            "interval",
                            "used",
                            "resets_at"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "status": {
                          "description": "pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.",
                          "enum": [
                            "active",
                            "pending",
                            "expired",
                            "revoked"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "name",
                        "status",
                        "prefix",
                        "scopes",
                        "spend_limit",
                        "expires_at",
                        "ip_allowlist",
                        "created_at",
                        "last_used_at",
                        "revoked_at",
                        "dashboard",
                        "previous_secret_expires_at",
                        "created_by_key",
                        "created_by_user"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get an API key",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Get an API key",
        "tags": [
          "API keys"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "patch": {
        "description": "Changes a key's name, scopes, spend limit, expiry or IP allowlist; absent fields keep their value. Takes effect within a minute everywhere. Free.\n\n**Auth:** an API key with the `admin` scope, or the dashboard session.",
        "operationId": "api_keys.update",
        "parameters": [
          {
            "description": "Key ID (key_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "expires_at": {
                    "description": "New expiry (RFC 3339, in the future); null: never expires.",
                    "format": "date-time",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "ip_allowlist": {
                    "description": "New allowlist; [] or null: any IP.",
                    "items": {
                      "maxLength": 64,
                      "type": "string"
                    },
                    "maxItems": 50,
                    "type": [
                      "array",
                      "null"
                    ]
                  },
                  "name": {
                    "description": "New label.",
                    "maxLength": 100,
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "scopes": {
                    "description": "New scopes (never more than the caller's own).",
                    "items": {
                      "enum": [
                        "endpoints",
                        "jobs",
                        "jobs:read",
                        "account:read",
                        "admin"
                      ],
                      "type": "string"
                    },
                    "maxItems": 5,
                    "minItems": 1,
                    "type": [
                      "array",
                      "null"
                    ]
                  },
                  "spend_limit": {
                    "description": "New spend limit; null removes it.",
                    "properties": {
                      "amount": {
                        "description": "Most credits the key may spend per interval; above it, requests fail with spend_limit_reached.",
                        "maximum": 1000000000,
                        "minimum": 1,
                        "type": "integer"
                      },
                      "interval": {
                        "description": "Calendar day or month, UTC.",
                        "enum": [
                          "day",
                          "month"
                        ],
                        "type": "string"
                      }
                    },
                    "required": [
                      "amount",
                      "interval"
                    ],
                    "type": [
                      "object",
                      "null"
                    ]
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "created_at": {
                          "description": "When the key was created, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "created_by_key": {
                          "description": "The API key (key_…) that last created this key, gave it the admin scope or rotated it: revoking that key also revokes this one if this one has admin. Null when none did, or a person has rotated it in the dashboard since.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "created_by_user": {
                          "description": "The person (GET /v1/members user_id) who created this key in the dashboard, or whose key created it. They may have left the account since. Null when no person did (an operator, or a key from before this was recorded).",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "dashboard": {
                          "description": "true for the account's built-in dashboard key: the dashboard's playground runs as it (so its requests are logged, counted and billed like any key's). Nobody holds its secret, so it works only from the signed-in dashboard. Only its spend_limit can be changed (to cap what the playground spends live); renaming, rescoping, restricting, rotating or revoking it is forbidden (details.reason dashboard_key). It is made on first use and revoked with the account.",
                          "type": "boolean"
                        },
                        "expires_at": {
                          "description": "When the key stops working, RFC 3339 UTC; null when it never expires.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "Key ID (key_…): manage the key with it. It is not the secret.",
                          "type": "string"
                        },
                        "ip_allowlist": {
                          "description": "IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; [] = any.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "last_used_at": {
                          "description": "About when the key was last used (updated at most hourly); null when never.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "name": {
                          "description": "Your label for the key.",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always api_key.",
                          "enum": [
                            "api_key"
                          ],
                          "type": "string"
                        },
                        "prefix": {
                          "description": "The secret's first characters, to recognize it.",
                          "type": "string"
                        },
                        "previous_secret_expires_at": {
                          "description": "Until then the secret this key had before its last rotation works too (rotate_secret), RFC 3339 UTC; null when none does.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "revoked_at": {
                          "description": "When the key was revoked; null while it is not.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "scopes": {
                          "description": "What the key may call: endpoints (data endpoints), jobs (create, read and cancel jobs; includes jobs:read), jobs:read (read jobs and their results), account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).",
                          "items": {
                            "enum": [
                              "endpoints",
                              "jobs",
                              "jobs:read",
                              "account:read",
                              "admin"
                            ],
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "spend_limit": {
                          "description": "The key's spend limit and what it used this interval; null when the key has none.",
                          "properties": {
                            "amount": {
                              "description": "Most credits the key may spend per interval.",
                              "type": "integer"
                            },
                            "interval": {
                              "description": "Calendar day or month, UTC.",
                              "enum": [
                                "day",
                                "month"
                              ],
                              "type": "string"
                            },
                            "resets_at": {
                              "description": "Start of the next interval, RFC 3339 UTC.",
                              "format": "date-time",
                              "type": "string"
                            },
                            "used": {
                              "description": "Credits the key spent this interval, plus what its requests in flight hold.",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "amount",
                            "interval",
                            "used",
                            "resets_at"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "status": {
                          "description": "pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.",
                          "enum": [
                            "active",
                            "pending",
                            "expired",
                            "revoked"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "name",
                        "status",
                        "prefix",
                        "scopes",
                        "spend_limit",
                        "expires_at",
                        "ip_allowlist",
                        "created_at",
                        "last_used_at",
                        "revoked_at",
                        "dashboard",
                        "previous_secret_expires_at",
                        "created_by_key",
                        "created_by_user"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Update an API key",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Update an API key",
        "tags": [
          "API keys"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/api_keys/{id}/rotate_secret": {
      "post": {
        "description": "Issues a new secret for the same key (same ID, settings and spend), shown once: store it now. The current secret keeps working for `previous_secret_expires_in` seconds, so you can deploy the new one without downtime, but only for calls that need no admin scope (others: forbidden, reason previous_secret). 0 stops it, and rotating again ends the oldest secret, within a minute everywhere: at most two secrets work. A rotation keeps the key, its jobs and every key it made: after a leak, revoke the key instead. A key may rotate itself, or a key it could have created; rotating another key puts that key below it. In the dashboard, a rotation frees the key from any key above it. Free.\n\n**Auth:** an API key with the `admin` scope, or the dashboard session.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "api_keys.rotate_secret",
        "parameters": [
          {
            "description": "Key ID (key_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "previous_secret_expires_in": {
                    "description": "Seconds the key's current secret keeps working after the new one is issued, at most 7 days; 0 stops it now. Default: 1 day.",
                    "maximum": 604800,
                    "minimum": 0,
                    "type": [
                      "integer",
                      "null"
                    ]
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "created_at": {
                          "description": "When the key was created, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "created_by_key": {
                          "description": "The API key (key_…) that last created this key, gave it the admin scope or rotated it: revoking that key also revokes this one if this one has admin. Null when none did, or a person has rotated it in the dashboard since.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "created_by_user": {
                          "description": "The person (GET /v1/members user_id) who created this key in the dashboard, or whose key created it. They may have left the account since. Null when no person did (an operator, or a key from before this was recorded).",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "dashboard": {
                          "description": "true for the account's built-in dashboard key: the dashboard's playground runs as it (so its requests are logged, counted and billed like any key's). Nobody holds its secret, so it works only from the signed-in dashboard. Only its spend_limit can be changed (to cap what the playground spends live); renaming, rescoping, restricting, rotating or revoking it is forbidden (details.reason dashboard_key). It is made on first use and revoked with the account.",
                          "type": "boolean"
                        },
                        "expires_at": {
                          "description": "When the key stops working, RFC 3339 UTC; null when it never expires.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "Key ID (key_…): manage the key with it. It is not the secret.",
                          "type": "string"
                        },
                        "ip_allowlist": {
                          "description": "IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; [] = any.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "last_used_at": {
                          "description": "About when the key was last used (updated at most hourly); null when never.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "name": {
                          "description": "Your label for the key.",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always api_key.",
                          "enum": [
                            "api_key"
                          ],
                          "type": "string"
                        },
                        "prefix": {
                          "description": "The secret's first characters, to recognize it.",
                          "type": "string"
                        },
                        "previous_secret_expires_at": {
                          "description": "Until then the secret this key had before its last rotation works too (rotate_secret), RFC 3339 UTC; null when none does.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "revoked_at": {
                          "description": "When the key was revoked; null while it is not.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "scopes": {
                          "description": "What the key may call: endpoints (data endpoints), jobs (create, read and cancel jobs; includes jobs:read), jobs:read (read jobs and their results), account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).",
                          "items": {
                            "enum": [
                              "endpoints",
                              "jobs",
                              "jobs:read",
                              "account:read",
                              "admin"
                            ],
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "secret": {
                          "description": "The key itself: send it in the x-api-key header. Shown only once: store it now.",
                          "type": "string"
                        },
                        "spend_limit": {
                          "description": "The key's spend limit and what it used this interval; null when the key has none.",
                          "properties": {
                            "amount": {
                              "description": "Most credits the key may spend per interval.",
                              "type": "integer"
                            },
                            "interval": {
                              "description": "Calendar day or month, UTC.",
                              "enum": [
                                "day",
                                "month"
                              ],
                              "type": "string"
                            },
                            "resets_at": {
                              "description": "Start of the next interval, RFC 3339 UTC.",
                              "format": "date-time",
                              "type": "string"
                            },
                            "used": {
                              "description": "Credits the key spent this interval, plus what its requests in flight hold.",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "amount",
                            "interval",
                            "used",
                            "resets_at"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "status": {
                          "description": "pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.",
                          "enum": [
                            "active",
                            "pending",
                            "expired",
                            "revoked"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "name",
                        "status",
                        "prefix",
                        "scopes",
                        "spend_limit",
                        "expires_at",
                        "ip_allowlist",
                        "created_at",
                        "last_used_at",
                        "revoked_at",
                        "dashboard",
                        "previous_secret_expires_at",
                        "created_by_key",
                        "created_by_user",
                        "secret"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Rotate an API key's secret",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Rotate an API key's secret",
        "tags": [
          "API keys"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/applemusic/album": {
      "get": {
        "description": "Returns an Apple Music album, single or EP from its link or ID in any country's store, with every track's ISRC, the label, UPC and genres. It also has the credited artists, full-size cover, release date, copyright, Apple's editorial notes, audio formats, each track's length and preview, more releases by the artist and the album's other versions. Legacy iTunes links work too.\n\nReturns `{data, meta}`: `data` is a `Album` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/applemusic/album/ (Markdown: https://socialtap.dev/docs/reference/applemusic/album/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/applemusic/album/index.md)",
          "url": "https://socialtap.dev/docs/reference/applemusic/album/"
        },
        "operationId": "applemusic.album.get",
        "parameters": [
          {
            "description": "The album: its link (music.apple.com/us/album/lover/1468058165), with or without the slug and the store, on music.apple.com, geo.music.apple.com or itunes.apple.com; or its ID alone (1468058165). A track's link (with ?i=) names a track: the Apple Music Track API reads it.",
            "example": "https://music.apple.com/us/album/lover/1468058165",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The album: its link (music.apple.com/us/album/lover/1468058165), with or without the slug and the store, on music.apple.com, geo.music.apple.com or itunes.apple.com; or its ID alone (1468058165). A track's link (with ?i=) names a track: the Apple Music Track API reads it.",
              "examples": [
                "https://music.apple.com/us/album/lover/1468058165"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store to read: an album has its own title language, track list and links per store, and can be missing from one. Default: the store in the link, else us.",
            "example": "us",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store to read: an album has its own title language, track list and links per store, and can be missing from one. Default: the store in the link, else us.",
              "examples": [
                "us"
              ],
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the link's l=, else the store's own language.",
            "example": "en-US",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the link's l=, else the store's own language.",
              "examples": [
                "en-US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "released_at"
                        ],
                        "artist_name": "Taylor Swift",
                        "artists": [
                          {
                            "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/6d/67/88/6d67888b-9e7f-53af-7853-0f91d6fd2332/ami_U003aidentity_U003a994af5c375f4c3aa96cd6ced4a700799-2026-09-25T04-00-05.358Z_cropped.png/1640x1640bb.jpg",
                            "display_name": "Taylor Swift",
                            "id": "159260351",
                            "is_verified": null,
                            "url": "https://music.apple.com/us/artist/taylor-swift/159260351",
                            "username": null
                          }
                        ],
                        "copyrights": [
                          {
                            "text": "℗ 2019 Taylor Swift",
                            "type": "p"
                          }
                        ],
                        "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music125/v4/49/3d/ab/493dab54-f920-9043-6181-80993b8116c9/19UMGIM53909.rgb.jpg/3900x3900bb.jpg",
                        "description": "There’s a reason Taylor Swift sounds so confident and cool on Lover, her seventh album and the most free-spirited yet. She’s in love—pure, steady, starry-eyed, shout-it-from-the-rooftops love. Arriving 13 years after her eponymous debut album—and following a string of songs that …",
                        "duration_ms": 3711368,
                        "genres": [
                          "Pop"
                        ],
                        "id": "1468058165",
                        "is_explicit": false,
                        "label": "Taylor Swift",
                        "metrics": {
                          "track_count": 18
                        },
                        "platform": "applemusic",
                        "platform_specific": {
                          "applemusic": {
                            "audio_traits": [
                              "atmos",
                              "lossless",
                              "lossy-stereo"
                            ],
                            "content_rating": null,
                            "editorial_summary": "A love letter to love itself.",
                            "is_complete": true,
                            "is_mastered_for_itunes": true,
                            "is_prerelease": false,
                            "more_by_artist": [
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/eb/e6/06/ebe606da-e00f-82d3-47f3-b79904eed541/17UM1IM24651.rgb.jpg/6000x6000bb.jpg",
                                "duration_ms": null,
                                "id": "1440933849",
                                "is_explicit": false,
                                "kind": "album",
                                "released_at": "2017-11-10T00:00:00Z",
                                "title": "reputation",
                                "track_count": 15,
                                "url": "https://music.apple.com/us/album/reputation/1440933849"
                              },
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/a4/86/59/a486593a-53c9-1c2a-5122-8f25339f7359/24UMGIM44778.rgb.jpg/3000x3000bb.jpg",
                                "duration_ms": null,
                                "id": "1742057774",
                                "is_explicit": true,
                                "kind": "album",
                                "released_at": "2024-04-19T00:00:00Z",
                                "title": "THE TORTURED POETS DEPARTMENT: THE ANTHOLOGY",
                                "track_count": 31,
                                "url": "https://music.apple.com/us/album/the-tortured-poets-department-the-anthology/1742057774"
                              },
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music115/v4/b5/80/dc/b580dca0-349d-036b-e09b-bd849f6affd8/20UMGIM64216.rgb.jpg/3000x3000bb.jpg",
                                "duration_ms": null,
                                "id": "1528112358",
                                "is_explicit": true,
                                "kind": "album",
                                "released_at": "2020-07-24T00:00:00Z",
                                "title": "folklore (deluxe version)",
                                "track_count": 17,
                                "url": "https://music.apple.com/us/album/folklore-deluxe-version/1528112358"
                              }
                            ],
                            "other_versions": [],
                            "rank": null,
                            "storefront": "us"
                          }
                        },
                        "released_at": "2019-08-23T00:00:00Z",
                        "title": "Lover",
                        "tracks": [
                          {
                            "artist_name": "Taylor Swift",
                            "artists": [
                              {
                                "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/6d/67/88/6d67888b-9e7f-53af-7853-0f91d6fd2332/ami_U003aidentity_U003a994af5c375f4c3aa96cd6ced4a700799-2026-09-25T04-00-05.358Z_cropped.png/1640x1640bb.jpg",
                                "display_name": "Taylor Swift",
                                "id": "159260351",
                                "is_verified": null,
                                "url": "https://music.apple.com/us/artist/taylor-swift/159260351",
                                "username": null
                              }
                            ],
                            "disc_number": 1,
                            "duration_ms": 170651,
                            "id": "1468058169",
                            "is_explicit": false,
                            "isrc": "USUG11901471",
                            "metrics": {
                              "view_count": null
                            },
                            "play_url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/9c/e2/97/9ce2976a-b1c8-aa80-3e94-f4562cbad53e/mzaf_13898706762824220632.plus.aac.ep.m4a",
                            "title": "I Forgot That You Existed",
                            "track_number": 1,
                            "url": "https://music.apple.com/us/album/i-forgot-that-you-existed/1468058165?i=1468058169"
                          },
                          {
                            "artist_name": "Taylor Swift",
                            "artists": [
                              {
                                "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/6d/67/88/6d67888b-9e7f-53af-7853-0f91d6fd2332/ami_U003aidentity_U003a994af5c375f4c3aa96cd6ced4a700799-2026-09-25T04-00-05.358Z_cropped.png/1640x1640bb.jpg",
                                "display_name": "Taylor Swift",
                                "id": "159260351",
                                "is_verified": null,
                                "url": "https://music.apple.com/us/artist/taylor-swift/159260351",
                                "username": null
                              }
                            ],
                            "disc_number": 1,
                            "duration_ms": 178426,
                            "id": "1468058171",
                            "is_explicit": false,
                            "isrc": "USUG11901472",
                            "metrics": {
                              "view_count": null
                            },
                            "play_url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/44/af/81/44af8168-9609-1b85-5048-ada08dceacf3/mzaf_5595361395314573470.plus.aac.ep.m4a",
                            "title": "Cruel Summer",
                            "track_number": 2,
                            "url": "https://music.apple.com/us/album/cruel-summer/1468058165?i=1468058171"
                          },
                          {
                            "artist_name": "Taylor Swift",
                            "artists": [
                              {
                                "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/6d/67/88/6d67888b-9e7f-53af-7853-0f91d6fd2332/ami_U003aidentity_U003a994af5c375f4c3aa96cd6ced4a700799-2026-09-25T04-00-05.358Z_cropped.png/1640x1640bb.jpg",
                                "display_name": "Taylor Swift",
                                "id": "159260351",
                                "is_verified": null,
                                "url": "https://music.apple.com/us/artist/taylor-swift/159260351",
                                "username": null
                              }
                            ],
                            "disc_number": 1,
                            "duration_ms": 221300,
                            "id": "1468058173",
                            "is_explicit": false,
                            "isrc": "USUG11901473",
                            "metrics": {
                              "view_count": null
                            },
                            "play_url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview211/v4/e0/db/47/e0db47b0-7f70-0631-0414-cd4777d2fb3e/mzaf_6008069204816798831.plus.aac.ep.m4a",
                            "title": "Lover",
                            "track_number": 3,
                            "url": "https://music.apple.com/us/album/lover/1468058165?i=1468058173"
                          }
                        ],
                        "type": "album",
                        "unknown_fields": [],
                        "upc": "00602508005275",
                        "url": "https://music.apple.com/us/album/lover/1468058165"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "applemusic",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 334,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "album",
                          "id": "1468058165",
                          "url": "https://music.apple.com/us/album/lover/1468058165"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ApplemusicAlbumResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Tracklist with ISRCs, label and UPC",
        "tags": [
          "Apple Music"
        ],
        "x-socialtap-endpoint": "applemusic.album",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "album",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/applemusic/artist": {
      "get": {
        "description": "Returns an Apple Music artist from its link or ID in any country's store, with its bio, genres, origin, top songs and albums. It also has the picture and banner, whether it is a person or a group, when it was born or formed, and its page's latest release, singles and EPs, music videos, playlists and similar artists, each with its ID, link, artwork and date.\n\nReturns `{data, meta}`: `data` is a `Profile` object (Apple Music calls it a artist) (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/applemusic/artist/ (Markdown: https://socialtap.dev/docs/reference/applemusic/artist/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/applemusic/artist/index.md)",
          "url": "https://socialtap.dev/docs/reference/applemusic/artist/"
        },
        "operationId": "applemusic.artist.get",
        "parameters": [
          {
            "description": "The artist: its link (music.apple.com/us/artist/taylor-swift/159260351, with or without the slug and the store, any of its section pages such as /top-songs or /see-all, on music.apple.com, geo.music.apple.com or itunes.apple.com) or the number in that link (159260351). Apple Music artists have no username.",
            "example": "159260351",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The artist: its link (music.apple.com/us/artist/taylor-swift/159260351, with or without the slug and the store, any of its section pages such as /top-songs or /see-all, on music.apple.com, geo.music.apple.com or itunes.apple.com) or the number in that link (159260351). Apple Music artists have no username.",
              "examples": [
                "159260351"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store to read: the same artist has its own bio language, sections and links per store. Default: the store in the link, else us.",
            "example": "us",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store to read: the same artist has its own bio language, sections and links per store. Default: the store in the link, else us.",
              "examples": [
                "us"
              ],
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the link's l=, else the store's own language.",
            "example": "en-US",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the link's l=, else the store's own language.",
              "examples": [
                "en-US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/6d/67/88/6d67888b-9e7f-53af-7853-0f91d6fd2332/ami_U003aidentity_U003a994af5c375f4c3aa96cd6ced4a700799-2026-09-25T04-00-05.358Z_cropped.png/1640x1640bb.jpg",
                        "banner_url": "https://is1-ssl.mzstatic.com/image/thumb/Features221/v4/a1/15/69/a11569c5-ad98-8244-db89-508129f379d6/9b2c00c3-0828-4828-b3e5-0f96e9c2650d.png/4320x1080sr.jpg",
                        "bio": "The country world feigned surprise when, after three albums of Music Row-indebted songcraft, Taylor Swift formally embraced pop on 2012’s Red. But no one should have been shocked: Any 14-year-old capable of persuading her parents to move from suburban Pennsylvania to Nashville fo…",
                        "category": null,
                        "country_code": null,
                        "created_at": null,
                        "display_name": "Taylor Swift",
                        "external_links": [],
                        "id": "159260351",
                        "is_private": null,
                        "is_verified": null,
                        "location": "West Reading, PA, United States",
                        "metrics": {
                          "follower_count": null,
                          "following_count": null,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "applemusic",
                        "platform_specific": {
                          "applemusic": {
                            "albums": [
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/a0/dd/fd/a0ddfd72-ee9e-f046-6466-a5dbefc696fa/26UM1IM21436.rgb.jpg/3000x3000bb.jpg",
                                "duration_ms": null,
                                "id": "6814997249",
                                "is_explicit": true,
                                "kind": "album",
                                "released_at": "2026-09-24T00:00:00Z",
                                "title": "The Life of a Showgirl: The Encore",
                                "track_count": 16,
                                "url": "https://music.apple.com/us/album/the-life-of-a-showgirl-the-encore/6814997249"
                              },
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/47/8a/b8/478ab8ac-d134-bad3-f700-364c83323bc6/26UMGIM11621.rgb.jpg/3000x3000bb.jpg",
                                "duration_ms": null,
                                "id": "1875381397",
                                "is_explicit": false,
                                "kind": "album",
                                "released_at": "2026-02-13T00:00:00Z",
                                "title": "Opalite (Official Music Video Extended Versions) - Single",
                                "track_count": 4,
                                "url": "https://music.apple.com/us/album/opalite-official-music-video-extended-versions-single/1875381397"
                              },
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/0e/e5/c7/0ee5c717-114f-f4e8-9f7c-e92dd6eb9152/25UM1IM74420.rgb.jpg/3000x3000bb.jpg",
                                "duration_ms": null,
                                "id": "1850496031",
                                "is_explicit": true,
                                "kind": "album",
                                "released_at": "2025-11-07T00:00:00Z",
                                "title": "The Life of a Showgirl + Acoustic Collection",
                                "track_count": 19,
                                "url": "https://music.apple.com/us/album/the-life-of-a-showgirl-acoustic-collection/1850496031"
                              }
                            ],
                            "amg_artist_id": null,
                            "born_or_formed": "December 13, 1989",
                            "editorial_summary": "Favorite Taylor’s artist page for updates on The Life of a Showgirl.",
                            "genres": [
                              "Pop"
                            ],
                            "is_group": false,
                            "latest_release": {
                              "artist_name": "Taylor Swift",
                              "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/89/98/98/8998984f-9a80-c3e1-d59d-e6a6db859e0c/26UM1IM31403.rgb.jpg/3000x3000bb.jpg",
                              "duration_ms": null,
                              "id": "6821937445",
                              "is_explicit": false,
                              "kind": "album",
                              "released_at": "2026-10-16T00:00:00Z",
                              "title": "Patient Zero - Single",
                              "track_count": 3,
                              "url": "https://music.apple.com/us/album/patient-zero-single/6821937445"
                            },
                            "music_videos": [
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Video221/v4/02/21/39/022139aa-083d-21c1-f0b9-cb7dc630dc98/26UM1IM22083.crop.jpg/3701x1912mv.jpg",
                                "duration_ms": 312384,
                                "id": "6816241368",
                                "is_explicit": false,
                                "kind": "music_video",
                                "released_at": "2026-09-28T00:00:00Z",
                                "title": "Patient Zero",
                                "track_count": null,
                                "url": "https://music.apple.com/us/music-video/patient-zero/6816241368"
                              },
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Video211/v4/19/2e/ca/192ecabc-b8d2-a613-06af-d608c1037642/26UM1IM22083.crop.jpg/3701x1912mv.jpg",
                                "duration_ms": 312384,
                                "id": "6818017941",
                                "is_explicit": false,
                                "kind": "music_video",
                                "released_at": "2026-09-24T00:00:00Z",
                                "title": "Patient Zero",
                                "track_count": null,
                                "url": "https://music.apple.com/us/music-video/patient-zero/6818017941"
                              },
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Video211/v4/e1/ef/ce/e1efced7-7023-bcaf-d157-0492240aa10c/26UM1IM28169.crop.jpg/1912x1072mv.jpg",
                                "duration_ms": 492139,
                                "id": "6818017943",
                                "is_explicit": false,
                                "kind": "music_video",
                                "released_at": "2026-09-24T00:00:00Z",
                                "title": "Patient Zero (Expanded Video)",
                                "track_count": null,
                                "url": "https://music.apple.com/us/music-video/patient-zero-expanded-video/6818017943"
                              }
                            ],
                            "playlists": [
                              {
                                "artist_name": "Apple Music Pop",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/6d/67/88/6d67888b-9e7f-53af-7853-0f91d6fd2332/ami_U003aidentity_U003a994af5c375f4c3aa96cd6ced4a700799-2026-09-25T04-00-05.358Z_cropped.png/1080x1080SC.FPESS05.jpg?l=en-US",
                                "duration_ms": null,
                                "id": "pl.3950454ced8c45a3b0cc693c2a7db97b",
                                "is_explicit": null,
                                "kind": "playlist",
                                "released_at": null,
                                "title": "Taylor Swift Essentials",
                                "track_count": null,
                                "url": "https://music.apple.com/us/playlist/taylor-swift-essentials/pl.3950454ced8c45a3b0cc693c2a7db97b"
                              },
                              {
                                "artist_name": "Apple Music Pop",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/6d/67/88/6d67888b-9e7f-53af-7853-0f91d6fd2332/ami_U003aidentity_U003a994af5c375f4c3aa96cd6ced4a700799-2026-09-25T04-00-05.358Z_cropped.png/1080x1080SC.MVESS05.jpg?l=en-US",
                                "duration_ms": null,
                                "id": "pl.6929cc16ba9e48878fcabb6af6412d0a",
                                "is_explicit": null,
                                "kind": "playlist",
                                "released_at": null,
                                "title": "Taylor Swift Video Essentials",
                                "track_count": null,
                                "url": "https://music.apple.com/us/playlist/taylor-swift-video-essentials/pl.6929cc16ba9e48878fcabb6af6412d0a"
                              },
                              {
                                "artist_name": "Apple Music Pop",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/6d/67/88/6d67888b-9e7f-53af-7853-0f91d6fd2332/ami_U003aidentity_U003a994af5c375f4c3aa96cd6ced4a700799-2026-09-25T04-00-05.358Z_cropped.png/1080x1080SC.FPSL03.jpg?l=en-US",
                                "duration_ms": null,
                                "id": "pl.57891bdd1bc840948374f1c4cbe9c840",
                                "is_explicit": null,
                                "kind": "playlist",
                                "released_at": null,
                                "title": "Taylor Swift’s Eras Tour Set List",
                                "track_count": null,
                                "url": "https://music.apple.com/us/playlist/taylor-swifts-eras-tour-set-list/pl.57891bdd1bc840948374f1c4cbe9c840"
                              }
                            ],
                            "similar_artists": [
                              {
                                "artist_name": null,
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/76/ca/e2/76cae283-f3ba-aa7f-6256-1817e9b5179f/ami-identity-2d92b3a772aa3368c092544fed8cac42-2026-06-26T22-33-16.704Z_cropped.png/2155x2155bb.jpg",
                                "duration_ms": null,
                                "id": "602767352",
                                "is_explicit": null,
                                "kind": "artist",
                                "released_at": null,
                                "title": "Lorde",
                                "track_count": null,
                                "url": "https://music.apple.com/us/artist/lorde/602767352"
                              },
                              {
                                "artist_name": null,
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages211/v4/06/f0/41/06f0418f-97d3-34f8-f0a3-3acc37964d89/ami-identity-b7ce039aac2c803c4620ff4ff18920ca-2026-08-06T15-12-54.044Z_cropped.png/3750x3750bb.jpg",
                                "duration_ms": null,
                                "id": "412778295",
                                "is_explicit": null,
                                "kind": "artist",
                                "released_at": null,
                                "title": "Ariana Grande",
                                "track_count": null,
                                "url": "https://music.apple.com/us/artist/ariana-grande/412778295"
                              },
                              {
                                "artist_name": null,
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages211/v4/47/79/63/47796327-5841-8691-ac9a-9e56e8e9d782/ami-identity-9dc79b57efd6f0e1ede00c6af8f8954c-2025-02-14T03-00-28.587Z_cropped.png/820x820bb.jpg",
                                "duration_ms": null,
                                "id": "280215834",
                                "is_explicit": null,
                                "kind": "artist",
                                "released_at": null,
                                "title": "Selena Gomez",
                                "track_count": null,
                                "url": "https://music.apple.com/us/artist/selena-gomez/280215834"
                              }
                            ],
                            "singles": [
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/89/98/98/8998984f-9a80-c3e1-d59d-e6a6db859e0c/26UM1IM31403.rgb.jpg/3000x3000bb.jpg",
                                "duration_ms": null,
                                "id": "6821937445",
                                "is_explicit": false,
                                "kind": "album",
                                "released_at": "2026-10-16T00:00:00Z",
                                "title": "Patient Zero - Single",
                                "track_count": 3,
                                "url": "https://music.apple.com/us/album/patient-zero-single/6821937445"
                              },
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/ae/c1/15/aec11538-c395-b88e-b0f9-7b5b07b8e676/ticket.zkazzkhn.jpg/3000x3000bb.jpg",
                                "duration_ms": null,
                                "id": "6778230429",
                                "is_explicit": false,
                                "kind": "album",
                                "released_at": "2026-06-12T00:00:00Z",
                                "title": "I Knew It, I Knew You (From \"Toy Story 5\") - Single",
                                "track_count": 3,
                                "url": "https://music.apple.com/us/album/i-knew-it-i-knew-you-from-toy-story-5-single/6778230429"
                              },
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/2b/14/dc/2b14dc4d-5173-7b38-b0ff-1c30daf5fa32/26UMGIM37308.rgb.jpg/3000x3000bb.jpg",
                                "duration_ms": null,
                                "id": "1888604488",
                                "is_explicit": false,
                                "kind": "album",
                                "released_at": "2026-03-31T00:00:00Z",
                                "title": "Elizabeth Taylor",
                                "track_count": 4,
                                "url": "https://music.apple.com/us/album/elizabeth-taylor/1888604488"
                              }
                            ],
                            "storefront": "us",
                            "top_songs": [
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/a0/dd/fd/a0ddfd72-ee9e-f046-6466-a5dbefc696fa/26UM1IM21436.rgb.jpg/3000x3000bb.jpg",
                                "duration_ms": 225868,
                                "id": "6814997425",
                                "is_explicit": false,
                                "kind": "song",
                                "released_at": "2026-09-24T00:00:00Z",
                                "title": "Patient Zero",
                                "track_count": null,
                                "url": "https://music.apple.com/us/album/patient-zero/6814997249?i=6814997425"
                              },
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/34/35/6c/34356cb4-bd0b-3bac-b118-1a6d7264dc64/26UMGIM69942.rgb.jpg/3000x3000bb.jpg",
                                "duration_ms": 178186,
                                "id": "6775527443",
                                "is_explicit": false,
                                "kind": "song",
                                "released_at": "2026-06-05T00:00:00Z",
                                "title": "I Knew It, I Knew You (From \"Toy Story 5\")",
                                "track_count": null,
                                "url": "https://music.apple.com/us/album/i-knew-it-i-knew-you-from-toy-story-5/6775527442?i=6775527443"
                              },
                              {
                                "artist_name": "Taylor Swift",
                                "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/2d/46/e0/2d46e0bc-8ab9-85dd-4b56-ee6951351034/25UM1IM19577.rgb.jpg/3000x3000bb.jpg",
                                "duration_ms": 226074,
                                "id": "1833328840",
                                "is_explicit": false,
                                "kind": "song",
                                "released_at": "2025-10-03T00:00:00Z",
                                "title": "The Fate of Ophelia",
                                "track_count": null,
                                "url": "https://music.apple.com/us/album/the-fate-of-ophelia/1833328839?i=1833328840"
                              }
                            ]
                          }
                        },
                        "type": "person",
                        "unknown_fields": [],
                        "url": "https://music.apple.com/us/artist/taylor-swift/159260351",
                        "username": null
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "applemusic",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 434,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "159260351",
                          "url": "https://music.apple.com/us/artist/taylor-swift/159260351"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ApplemusicArtistResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Bio, origin, genres, top songs and albums",
        "tags": [
          "Apple Music"
        ],
        "x-socialtap-endpoint": "applemusic.artist",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/applemusic/search_albums": {
      "get": {
        "description": "Searches Apple Music albums, singles and EPs by keyword in any country's store and returns them a page at a time, with label, UPC and track count. Each has the credited artists with their IDs, full-size cover, release date, copyright, genres, explicit rating, audio formats, Apple's notes and its Mastered for iTunes badge. The Apple Music Album API returns the tracks.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Album` items (the shared schema, the same on every platform), Apple Music's own relevance order for the query. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/applemusic/search_albums/ (Markdown: https://socialtap.dev/docs/reference/applemusic/search_albums/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/applemusic/search_albums/index.md)",
          "url": "https://socialtap.dev/docs/reference/applemusic/search_albums/"
        },
        "operationId": "applemusic.search_albums.list",
        "parameters": [
          {
            "description": "What to search for: an album's title, an artist's name, or both together, in any language. Apple matches it as its web player's search box does.",
            "example": "lover",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to search for: an album's title, an artist's name, or both together, in any language. Apple matches it as its web player's search box does.",
              "examples": [
                "lover"
              ],
              "maxLength": 500,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store to search: the results, their titles and their links differ by store. A country with no Apple Music store returns invalid_input. Default: US. UK is read as GB.",
            "example": "JP",
            "in": "query",
            "name": "country",
            "schema": {
              "default": "US",
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store to search: the results, their titles and their links differ by store. A country with no Apple Music store returns invalid_input. Default: US. UK is read as GB.",
              "examples": [
                "JP"
              ],
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the store's own language.",
            "example": "en-US",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the store's own language.",
              "examples": [
                "en-US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "released_at"
                          ],
                          "artist_name": "Taylor Swift",
                          "artists": [
                            {
                              "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/6d/67/88/6d67888b-9e7f-53af-7853-0f91d6fd2332/ami_U003aidentity_U003a994af5c375f4c3aa96cd6ced4a700799-2026-09-25T04-00-05.358Z_cropped.png/1640x1640bb.jpg",
                              "display_name": "Taylor Swift",
                              "id": "159260351",
                              "is_verified": null,
                              "url": "https://music.apple.com/us/artist/taylor-swift/159260351",
                              "username": null
                            }
                          ],
                          "copyrights": [
                            {
                              "text": "℗ 2019 Taylor Swift",
                              "type": "p"
                            }
                          ],
                          "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music125/v4/49/3d/ab/493dab54-f920-9043-6181-80993b8116c9/19UMGIM53909.rgb.jpg/3900x3900bb.jpg",
                          "description": "There’s a reason Taylor Swift sounds so confident and cool on Lover, her seventh album and the most free-spirited yet. She’s in love—pure, steady, starry-eyed, shout-it-from-the-rooftops love. Arriving 13 years after her eponymous debut album—and following a string of songs that …",
                          "duration_ms": null,
                          "genres": [
                            "Pop"
                          ],
                          "id": "1468058165",
                          "is_explicit": false,
                          "label": "Taylor Swift",
                          "metrics": {
                            "track_count": 18
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "audio_traits": [
                                "atmos",
                                "lossless",
                                "lossy-stereo"
                              ],
                              "content_rating": null,
                              "editorial_summary": "A love letter to love itself.",
                              "is_complete": true,
                              "is_mastered_for_itunes": true,
                              "is_prerelease": false,
                              "more_by_artist": [],
                              "other_versions": [],
                              "rank": null,
                              "storefront": "us"
                            }
                          },
                          "released_at": "2019-08-23T00:00:00Z",
                          "title": "Lover",
                          "tracks": [],
                          "type": "album",
                          "unknown_fields": [
                            "tracks",
                            "tracks[].artists",
                            "platform_specific.applemusic.more_by_artist"
                          ],
                          "upc": "00602508005275",
                          "url": "https://music.apple.com/us/album/lover/1468058165"
                        },
                        {
                          "approximate_fields": [
                            "released_at"
                          ],
                          "artist_name": "vaultboy",
                          "artists": [
                            {
                              "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/7d/2d/2d/7d2d2da3-ca61-3cea-6478-fddbc1a92f6d/49a6d979-37fe-4612-9ce0-4dbd71b4bd43_file_cropped.png/2000x2000bb.jpg",
                              "display_name": "vaultboy",
                              "id": "1542387120",
                              "is_verified": null,
                              "url": "https://music.apple.com/us/artist/vaultboy/1542387120",
                              "username": null
                            }
                          ],
                          "copyrights": [
                            {
                              "text": "℗ 2026 broke",
                              "type": "p"
                            }
                          ],
                          "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/8a/fc/30/8afc3056-fd3b-3ba4-18b0-042e28b12576/612891173772.jpg/1400x1400bb.jpg",
                          "description": null,
                          "duration_ms": null,
                          "genres": [
                            "Pop"
                          ],
                          "id": "6798022501",
                          "is_explicit": true,
                          "label": "broke",
                          "metrics": {
                            "track_count": 1
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "audio_traits": [
                                "lossless",
                                "lossy-stereo"
                              ],
                              "content_rating": "explicit",
                              "editorial_summary": null,
                              "is_complete": true,
                              "is_mastered_for_itunes": false,
                              "is_prerelease": false,
                              "more_by_artist": [],
                              "other_versions": [],
                              "rank": null,
                              "storefront": "us"
                            }
                          },
                          "released_at": "2026-08-14T00:00:00Z",
                          "title": "LOVER - Single",
                          "tracks": [],
                          "type": "single",
                          "unknown_fields": [
                            "tracks",
                            "tracks[].artists",
                            "platform_specific.applemusic.more_by_artist"
                          ],
                          "upc": "612891173772",
                          "url": "https://music.apple.com/us/album/lover-single/6798022501"
                        },
                        {
                          "approximate_fields": [
                            "released_at"
                          ],
                          "artist_name": "Park Hyo Shin",
                          "artists": [
                            {
                              "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/Features211/v4/58/01/5f/58015f0a-bc1f-5814-080b-8edc678e95ea/mzl.aktvsodt.jpg/4000x4000bb.jpg",
                              "display_name": "Park Hyo Shin",
                              "id": "292946954",
                              "is_verified": null,
                              "url": "https://music.apple.com/us/artist/park-hyo-shin/292946954",
                              "username": null
                            }
                          ],
                          "copyrights": [
                            {
                              "text": "℗ 2019 (주)글러브엔터테인먼트, under license to Dreamus",
                              "type": "p"
                            }
                          ],
                          "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music116/v4/17/c9/8e/17c98e9b-8a8b-1dcd-c0b1-bf3f1208f1d8/8809829710020.jpg/3000x3000bb.jpg",
                          "description": null,
                          "duration_ms": null,
                          "genres": [
                            "Rock",
                            "Pop",
                            "K-Pop"
                          ],
                          "id": "1698506754",
                          "is_explicit": false,
                          "label": "(주)글러브엔터테인먼트",
                          "metrics": {
                            "track_count": 1
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "audio_traits": [
                                "lossless",
                                "lossy-stereo"
                              ],
                              "content_rating": null,
                              "editorial_summary": null,
                              "is_complete": true,
                              "is_mastered_for_itunes": false,
                              "is_prerelease": false,
                              "more_by_artist": [],
                              "other_versions": [],
                              "rank": null,
                              "storefront": "us"
                            }
                          },
                          "released_at": "2019-06-29T00:00:00Z",
                          "title": "LOVER - Single",
                          "tracks": [],
                          "type": "single",
                          "unknown_fields": [
                            "tracks",
                            "tracks[].artists",
                            "platform_specific.applemusic.more_by_artist"
                          ],
                          "upc": "8809829710020",
                          "url": "https://music.apple.com/us/album/lover-single/1698506754"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "applemusic",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 400,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ApplemusicSearch_albumsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Albums, singles and EPs by keyword",
        "tags": [
          "Apple Music"
        ],
        "x-socialtap-endpoint": "applemusic.search_albums",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Apple Music's own relevance order for the query",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "album",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/applemusic/search_artists": {
      "get": {
        "description": "Searches Apple Music artists by name in any country's store and returns them a page at a time, each with its ID, bio, genres and origin. Each also has whether it is a person or a group, when it was born or formed, and its full-size picture and banner. The Apple Music Artist API adds the top songs, albums and similar artists.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Profile` items (Apple Music calls it a artist) (the shared schema, the same on every platform), Apple Music's own relevance order for the query. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/applemusic/search_artists/ (Markdown: https://socialtap.dev/docs/reference/applemusic/search_artists/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/applemusic/search_artists/index.md)",
          "url": "https://socialtap.dev/docs/reference/applemusic/search_artists/"
        },
        "operationId": "applemusic.search_artists.list",
        "parameters": [
          {
            "description": "What to search for: an artist's or a band's name, in any language. Apple matches it as its web player's search box does.",
            "example": "adele",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to search for: an artist's or a band's name, in any language. Apple matches it as its web player's search box does.",
              "examples": [
                "adele"
              ],
              "maxLength": 500,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store to search: the results, their names and their links differ by store. A country with no Apple Music store returns invalid_input. Default: US. UK is read as GB.",
            "example": "JP",
            "in": "query",
            "name": "country",
            "schema": {
              "default": "US",
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store to search: the results, their names and their links differ by store. A country with no Apple Music store returns invalid_input. Default: US. UK is read as GB.",
              "examples": [
                "JP"
              ],
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the store's own language.",
            "example": "en-US",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the store's own language.",
              "examples": [
                "en-US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/Features125/v4/a2/2d/df/a22ddf71-9254-043c-c162-11fbc25c5ff3/mzl.ilbjswky.jpg/2400x2400bb.jpg",
                          "banner_url": "https://is1-ssl.mzstatic.com/image/thumb/Features69/v4/49/b8/ed/49b8edd2-17ed-0aa2-c14a-8cdee66b648c/pr_source.png/4320x1080bb.jpg",
                          "bio": "Dozens of British artists share Adele’s origins—BRIT School, Myspace, pop stardom—but it takes rare talent to have your voice declared timeless in your career’s first flush. Adele Adkins honed hers as a kid in her North London bedroom, imitating Etta James every night for an hour…",
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "Adele",
                          "external_links": [],
                          "id": "262836961",
                          "is_private": null,
                          "is_verified": null,
                          "location": "Tottenham, London, England",
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "albums": [],
                              "amg_artist_id": null,
                              "born_or_formed": "May 5, 1988",
                              "editorial_summary": null,
                              "genres": [
                                "Pop"
                              ],
                              "is_group": false,
                              "latest_release": null,
                              "music_videos": [],
                              "playlists": [],
                              "similar_artists": [],
                              "singles": [],
                              "storefront": "us",
                              "top_songs": []
                            }
                          },
                          "type": "person",
                          "unknown_fields": [
                            "platform_specific.applemusic.top_songs",
                            "platform_specific.applemusic.albums",
                            "platform_specific.applemusic.singles"
                          ],
                          "url": "https://music.apple.com/us/artist/adele/262836961",
                          "username": null
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/Music124/v4/4f/60/52/4f6052f0-54d7-5d45-3c3c-f957a969c390/887396302181.tif/1500x1500ac.jpg",
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "Adele",
                          "external_links": [],
                          "id": "563040812",
                          "is_private": null,
                          "is_verified": null,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "albums": [],
                              "amg_artist_id": null,
                              "born_or_formed": null,
                              "editorial_summary": null,
                              "genres": [
                                "Christian"
                              ],
                              "is_group": false,
                              "latest_release": null,
                              "music_videos": [],
                              "playlists": [],
                              "similar_artists": [],
                              "singles": [],
                              "storefront": "us",
                              "top_songs": []
                            }
                          },
                          "type": "person",
                          "unknown_fields": [
                            "platform_specific.applemusic.top_songs",
                            "platform_specific.applemusic.albums",
                            "platform_specific.applemusic.singles"
                          ],
                          "url": "https://music.apple.com/us/artist/adele/563040812",
                          "username": null
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": null,
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "Adele",
                          "external_links": [],
                          "id": "1268134202",
                          "is_private": null,
                          "is_verified": null,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "albums": [],
                              "amg_artist_id": null,
                              "born_or_formed": null,
                              "editorial_summary": null,
                              "genres": [
                                "Pop"
                              ],
                              "is_group": false,
                              "latest_release": null,
                              "music_videos": [],
                              "playlists": [],
                              "similar_artists": [],
                              "singles": [],
                              "storefront": "us",
                              "top_songs": []
                            }
                          },
                          "type": "person",
                          "unknown_fields": [
                            "platform_specific.applemusic.top_songs",
                            "platform_specific.applemusic.albums",
                            "platform_specific.applemusic.singles"
                          ],
                          "url": "https://music.apple.com/us/artist/adele/1268134202",
                          "username": null
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "applemusic",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 313,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ApplemusicSearch_artistsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Artists by name, with bio and origin",
        "tags": [
          "Apple Music"
        ],
        "x-socialtap-endpoint": "applemusic.search_artists",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Apple Music's own relevance order for the query",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/applemusic/search_playlists": {
      "get": {
        "description": "Searches Apple Music playlists or radio stations by keyword in any country's store and returns them a page at a time, with who curates each. A playlist has its description, Apple's one-line note, cover, track count, whether it is editorial, when it last changed and its audio format. A station has its kind, band and frequency, whether it streams live and whether only subscribers can play it.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Playlist` items (the shared schema, the same on every platform), Apple Music's own relevance order for the query. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/applemusic/search_playlists/ (Markdown: https://socialtap.dev/docs/reference/applemusic/search_playlists/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/applemusic/search_playlists/index.md)",
          "url": "https://socialtap.dev/docs/reference/applemusic/search_playlists/"
        },
        "operationId": "applemusic.search_playlists.list",
        "parameters": [
          {
            "description": "What to search for: a playlist's or station's name, an artist, a mood, a genre, in any language. Apple matches it as its web player's search box does.",
            "example": "workout",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to search for: a playlist's or station's name, an artist, a mood, a genre, in any language. Apple matches it as its web player's search box does.",
              "examples": [
                "workout"
              ],
              "maxLength": 500,
              "type": "string"
            }
          },
          {
            "description": "What to list: playlists (the default) or radio stations. Both come back in the same playlist shape, and platform_type says which it is.",
            "example": "station",
            "in": "query",
            "name": "kind",
            "schema": {
              "default": "playlist",
              "description": "What to list: playlists (the default) or radio stations. Both come back in the same playlist shape, and platform_type says which it is.",
              "enum": [
                "playlist",
                "station"
              ],
              "examples": [
                "station"
              ],
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store to search: the results, their titles and their links differ by store. A country with no Apple Music store returns invalid_input. Default: US. UK is read as GB.",
            "example": "JP",
            "in": "query",
            "name": "country",
            "schema": {
              "default": "US",
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store to search: the results, their titles and their links differ by store. A country with no Apple Music store returns invalid_input. Default: US. UK is read as GB.",
              "examples": [
                "JP"
              ],
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the store's own language.",
            "example": "en-US",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the store's own language.",
              "examples": [
                "en-US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "description": "Here’s where you’ll find the best tunes for working out that are making the rounds online. Just like your feed, this playlist is constantly being updated—if you hear a song you like, add it to your library.",
                          "id": "pl.ee26872314e349ddaa91050dadbbaaff",
                          "is_collaborative": false,
                          "metrics": {
                            "post_count": 100
                          },
                          "owner": {
                            "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/Features211/v4/9a/7c/44/9a7c4409-33aa-4b66-f2e7-e4362c01f490/93eac142-43a5-4614-b866-614702fc22ba.png/1080x1080bb.jpg",
                            "display_name": "Apple Music Fitness",
                            "id": null,
                            "is_verified": null,
                            "url": "https://music.apple.com/us/curator/apple-music-fitness/1558256909",
                            "username": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "audio_traits": [],
                              "band": null,
                              "curator_id": "1558256909",
                              "editorial_kind": null,
                              "editorial_sub_kind": null,
                              "editorial_summary": "The best tunes from your social feeds for working out.",
                              "frequency": null,
                              "is_chart": false,
                              "is_collaborative": false,
                              "is_live": null,
                              "is_subscription_required": null,
                              "last_modified_at": "2026-10-30T04:02:36Z",
                              "media_kind": null,
                              "playlist_type": "editorial",
                              "rank": null,
                              "station_kind": null,
                              "storefront": "us"
                            }
                          },
                          "platform_type": "playlist",
                          "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Features126/v4/46/9d/7b/469d7b24-d343-9f0a-27c0-2112b40dc513/d9221f7b-fe58-47c1-a1ea-2f5a19c03168.png/1080x1080SC.DN02.jpg?l=en-US",
                          "title": "Viral Workout",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://music.apple.com/us/playlist/viral-workout/pl.ee26872314e349ddaa91050dadbbaaff"
                        },
                        {
                          "approximate_fields": [],
                          "description": "Get your sexy back with pop's divas, rap’s heavy hitters, and more. This playlist is updated regularly with the biggest hits of the 2000s. If you hear something you like, add it to your library.",
                          "id": "pl.89b29d098bb64215a3caac990b3d80e0",
                          "is_collaborative": false,
                          "metrics": {
                            "post_count": 100
                          },
                          "owner": {
                            "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/Features211/v4/9a/7c/44/9a7c4409-33aa-4b66-f2e7-e4362c01f490/93eac142-43a5-4614-b866-614702fc22ba.png/1080x1080bb.jpg",
                            "display_name": "Apple Music Fitness",
                            "id": null,
                            "is_verified": null,
                            "url": "https://music.apple.com/us/curator/apple-music-fitness/1558256909",
                            "username": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "audio_traits": [],
                              "band": null,
                              "curator_id": "1558256909",
                              "editorial_kind": null,
                              "editorial_sub_kind": null,
                              "editorial_summary": "Get your sexy back with pop's divas, rap’s heavy hitters, and more.",
                              "frequency": null,
                              "is_chart": false,
                              "is_collaborative": false,
                              "is_live": null,
                              "is_subscription_required": null,
                              "last_modified_at": "2026-08-18T21:11:32Z",
                              "media_kind": null,
                              "playlist_type": "editorial",
                              "rank": null,
                              "station_kind": null,
                              "storefront": "us"
                            }
                          },
                          "platform_type": "playlist",
                          "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Features116/v4/40/99/84/409984d1-6457-53fe-9575-e1f173f2576c/9180e7c7-6797-4bdd-bc1c-3e6b0d010de7.png/1080x1080SC.DN02.jpg?l=en-US",
                          "title": "2000s Workout",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://music.apple.com/us/playlist/2000s-workout/pl.89b29d098bb64215a3caac990b3d80e0"
                        },
                        {
                          "approximate_fields": [],
                          "description": "The best songs for getting you through that final lap or set. Our editors regularly update this playlist—if you hear something you like, add it to your library.",
                          "id": "pl.4c62f568a0d64293a9c362037175c09b",
                          "is_collaborative": false,
                          "metrics": {
                            "post_count": 139
                          },
                          "owner": {
                            "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/Features211/v4/9a/7c/44/9a7c4409-33aa-4b66-f2e7-e4362c01f490/93eac142-43a5-4614-b866-614702fc22ba.png/1080x1080bb.jpg",
                            "display_name": "Apple Music Fitness",
                            "id": null,
                            "is_verified": null,
                            "url": "https://music.apple.com/us/curator/apple-music-fitness/1558256909",
                            "username": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "audio_traits": [],
                              "band": null,
                              "curator_id": "1558256909",
                              "editorial_kind": null,
                              "editorial_sub_kind": null,
                              "editorial_summary": "The best songs for getting you through that final lap or set.",
                              "frequency": null,
                              "is_chart": false,
                              "is_collaborative": false,
                              "is_live": null,
                              "is_subscription_required": null,
                              "last_modified_at": "2026-10-23T22:50:48Z",
                              "media_kind": null,
                              "playlist_type": "editorial",
                              "rank": null,
                              "station_kind": null,
                              "storefront": "us"
                            }
                          },
                          "platform_type": "playlist",
                          "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Features125/v4/b9/18/02/b9180250-a496-520c-70eb-6f01710b083d/U0MtTVMtV1ctSGlwLUhvcF9Xb3Jrb3V0LUFEQU1fSUQ9MTAwNDc4MTM5Ni5wbmc.png/1080x1080SC.DN02.jpg?l=en-US",
                          "title": "Hip-Hop Workout",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://music.apple.com/us/playlist/hip-hop-workout/pl.4c62f568a0d64293a9c362037175c09b"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "applemusic",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 404,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ApplemusicSearch_playlistsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Playlists and radio stations by keyword",
        "tags": [
          "Apple Music"
        ],
        "x-socialtap-endpoint": "applemusic.search_playlists",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Apple Music's own relevance order for the query",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "playlist",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/applemusic/search_tracks": {
      "get": {
        "description": "Searches Apple Music songs, music videos or radio episodes by keyword in any country's store and returns them a page at a time, each with its ISRC. Each also has the credited artists with their IDs, album, length, release date, composer, genres, explicit rating, audio formats, whether Apple has its lyrics, artwork and a preview clip. A radio episode has its show as author and when it aired.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Post` items (Apple Music calls it a track) (the shared schema, the same on every platform), Apple Music's own relevance order for the query. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/applemusic/search_tracks/ (Markdown: https://socialtap.dev/docs/reference/applemusic/search_tracks/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/applemusic/search_tracks/index.md)",
          "url": "https://socialtap.dev/docs/reference/applemusic/search_tracks/"
        },
        "operationId": "applemusic.search_tracks.list",
        "parameters": [
          {
            "description": "What to search for: a song's or video's title, an artist's name, an album's, or any of them together, in any language. Apple matches it as its web player's search box does.",
            "example": "taylor swift",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to search for: a song's or video's title, an artist's name, an album's, or any of them together, in any language. Apple matches it as its web player's search box does.",
              "examples": [
                "taylor swift"
              ],
              "maxLength": 500,
              "type": "string"
            }
          },
          {
            "description": "What to list: songs (the default), music videos or radio episodes. Every kind comes back in the same post shape, and platform_type says which it is.",
            "example": "music_video",
            "in": "query",
            "name": "kind",
            "schema": {
              "default": "song",
              "description": "What to list: songs (the default), music videos or radio episodes. Every kind comes back in the same post shape, and platform_type says which it is.",
              "enum": [
                "song",
                "music_video",
                "radio_episode"
              ],
              "examples": [
                "music_video"
              ],
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store to search: the results, their titles and their links differ by store. A country with no Apple Music store returns invalid_input. Default: US. UK is read as GB.",
            "example": "JP",
            "in": "query",
            "name": "country",
            "schema": {
              "default": "US",
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store to search: the results, their titles and their links differ by store. A country with no Apple Music store returns invalid_input. Default: US. UK is read as GB.",
              "examples": [
                "JP"
              ],
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the store's own language.",
            "example": "en-US",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the store's own language.",
              "examples": [
                "en-US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/6d/67/88/6d67888b-9e7f-53af-7853-0f91d6fd2332/ami_U003aidentity_U003a994af5c375f4c3aa96cd6ced4a700799-2026-09-25T04-00-05.358Z_cropped.png/1640x1640bb.jpg",
                            "display_name": "Taylor Swift",
                            "id": "159260351",
                            "is_verified": null,
                            "url": "https://music.apple.com/us/artist/taylor-swift/159260351",
                            "username": null
                          },
                          "coauthors": [],
                          "duration_ms": 225868,
                          "hashtags": [],
                          "id": "6814997425",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/a0/dd/fd/a0ddfd72-ee9e-f046-6466-a5dbefc696fa/26UM1IM21436.rgb.jpg/3000x3000bb.jpg",
                              "type": "audio",
                              "url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/ec/c8/21/ecc821bd-1252-51fe-08f0-f3d548dcc91b/mzaf_6909590374062866776.plus.aac.ep.m4a",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "air_ended_at": null,
                              "album_artist_name": "Taylor Swift",
                              "album_id": "6814997249",
                              "album_title": "The Life of a Showgirl: The Encore",
                              "album_url": "https://music.apple.com/us/album/the-life-of-a-showgirl-the-encore/6814997249",
                              "artist_name": "Taylor Swift",
                              "attribution": null,
                              "audio_locale": "en-US",
                              "audio_traits": [
                                "atmos",
                                "lossless",
                                "lossy-stereo"
                              ],
                              "composer_name": "Taylor Swift, Max Martin & Shellback",
                              "content_rating": null,
                              "curator_id": null,
                              "disc_number": 2,
                              "genres": [
                                "Pop"
                              ],
                              "is_4k": null,
                              "is_apple_digital_master": true,
                              "is_explicit": false,
                              "is_hdr": null,
                              "is_live": null,
                              "is_lyrics_available": true,
                              "is_mastered_for_itunes": true,
                              "is_time_synced_lyrics_available": true,
                              "isrc": "USUG12602391",
                              "long_note": null,
                              "movement_count": null,
                              "movement_name": null,
                              "movement_number": null,
                              "rank": null,
                              "storefront": "us",
                              "track_number": 1,
                              "video_traits": [],
                              "work_name": null
                            }
                          },
                          "platform_type": "song",
                          "published_at": "2026-09-24T00:00:00Z",
                          "text": null,
                          "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/a0/dd/fd/a0ddfd72-ee9e-f046-6466-a5dbefc696fa/26UM1IM21436.rgb.jpg/3000x3000bb.jpg",
                          "title": "Patient Zero",
                          "type": "audio",
                          "unknown_fields": [],
                          "url": "https://music.apple.com/us/album/patient-zero/6814997249?i=6814997425"
                        },
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/6d/67/88/6d67888b-9e7f-53af-7853-0f91d6fd2332/ami_U003aidentity_U003a994af5c375f4c3aa96cd6ced4a700799-2026-09-25T04-00-05.358Z_cropped.png/1640x1640bb.jpg",
                            "display_name": "Taylor Swift",
                            "id": "159260351",
                            "is_verified": null,
                            "url": "https://music.apple.com/us/artist/taylor-swift/159260351",
                            "username": null
                          },
                          "coauthors": [],
                          "duration_ms": 226074,
                          "hashtags": [],
                          "id": "1833328840",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/2d/46/e0/2d46e0bc-8ab9-85dd-4b56-ee6951351034/25UM1IM19577.rgb.jpg/3000x3000bb.jpg",
                              "type": "audio",
                              "url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/4b/07/28/4b07285f-b50c-7aff-cb40-2d732256b703/mzaf_14590041634085649439.plus.aac.ep.m4a",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "air_ended_at": null,
                              "album_artist_name": "Taylor Swift",
                              "album_id": "1833328839",
                              "album_title": "The Life of a Showgirl",
                              "album_url": "https://music.apple.com/us/album/the-life-of-a-showgirl/1833328839",
                              "artist_name": "Taylor Swift",
                              "attribution": null,
                              "audio_locale": "en-US",
                              "audio_traits": [
                                "atmos",
                                "lossless",
                                "lossy-stereo"
                              ],
                              "composer_name": "Taylor Swift, Max Martin & Shellback",
                              "content_rating": null,
                              "curator_id": null,
                              "disc_number": 1,
                              "genres": [
                                "Pop"
                              ],
                              "is_4k": null,
                              "is_apple_digital_master": true,
                              "is_explicit": false,
                              "is_hdr": null,
                              "is_live": null,
                              "is_lyrics_available": true,
                              "is_mastered_for_itunes": true,
                              "is_time_synced_lyrics_available": true,
                              "isrc": "USUG12506436",
                              "long_note": null,
                              "movement_count": null,
                              "movement_name": null,
                              "movement_number": null,
                              "rank": null,
                              "storefront": "us",
                              "track_number": 1,
                              "video_traits": [],
                              "work_name": null
                            }
                          },
                          "platform_type": "song",
                          "published_at": "2025-10-03T00:00:00Z",
                          "text": null,
                          "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/2d/46/e0/2d46e0bc-8ab9-85dd-4b56-ee6951351034/25UM1IM19577.rgb.jpg/3000x3000bb.jpg",
                          "title": "The Fate of Ophelia",
                          "type": "audio",
                          "unknown_fields": [],
                          "url": "https://music.apple.com/us/album/the-fate-of-ophelia/1833328839?i=1833328840"
                        },
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/6d/67/88/6d67888b-9e7f-53af-7853-0f91d6fd2332/ami_U003aidentity_U003a994af5c375f4c3aa96cd6ced4a700799-2026-09-25T04-00-05.358Z_cropped.png/1640x1640bb.jpg",
                            "display_name": "Taylor Swift",
                            "id": "159260351",
                            "is_verified": null,
                            "url": "https://music.apple.com/us/artist/taylor-swift/159260351",
                            "username": null
                          },
                          "coauthors": [],
                          "duration_ms": 178186,
                          "hashtags": [],
                          "id": "6775527443",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/34/35/6c/34356cb4-bd0b-3bac-b118-1a6d7264dc64/26UMGIM69942.rgb.jpg/3000x3000bb.jpg",
                              "type": "audio",
                              "url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/73/76/42/737642e6-c478-bed7-f11f-efee96072450/mzaf_12192094637498612451.plus.aac.ep.m4a",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "air_ended_at": null,
                              "album_artist_name": "Taylor Swift",
                              "album_id": "6775527442",
                              "album_title": "I Knew It, I Knew You (From \"Toy Story 5\") - Single",
                              "album_url": "https://music.apple.com/us/album/i-knew-it-i-knew-you-from-toy-story-5-single/6775527442",
                              "artist_name": "Taylor Swift",
                              "attribution": null,
                              "audio_locale": "en-US",
                              "audio_traits": [
                                "atmos",
                                "lossless",
                                "lossy-stereo"
                              ],
                              "composer_name": "Taylor Swift & Jack Antonoff",
                              "content_rating": null,
                              "curator_id": null,
                              "disc_number": 1,
                              "genres": [
                                "Country"
                              ],
                              "is_4k": null,
                              "is_apple_digital_master": true,
                              "is_explicit": false,
                              "is_hdr": null,
                              "is_live": null,
                              "is_lyrics_available": true,
                              "is_mastered_for_itunes": true,
                              "is_time_synced_lyrics_available": true,
                              "isrc": "USWD12641055",
                              "long_note": null,
                              "movement_count": null,
                              "movement_name": null,
                              "movement_number": null,
                              "rank": null,
                              "storefront": "us",
                              "track_number": 1,
                              "video_traits": [],
                              "work_name": null
                            }
                          },
                          "platform_type": "song",
                          "published_at": "2026-06-05T00:00:00Z",
                          "text": null,
                          "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/34/35/6c/34356cb4-bd0b-3bac-b118-1a6d7264dc64/26UMGIM69942.rgb.jpg/3000x3000bb.jpg",
                          "title": "I Knew It, I Knew You (From \"Toy Story 5\")",
                          "type": "audio",
                          "unknown_fields": [],
                          "url": "https://music.apple.com/us/album/i-knew-it-i-knew-you-from-toy-story-5/6775527442?i=6775527443"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "applemusic",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 494,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ApplemusicSearch_tracksResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Songs, music videos and radio episodes by keyword",
        "tags": [
          "Apple Music"
        ],
        "x-socialtap-endpoint": "applemusic.search_tracks",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Apple Music's own relevance order for the query",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/applemusic/top_albums": {
      "get": {
        "description": "Returns Apple Music's chart of the most played albums in a country's store, top first, a page at a time, with each album's rank, label and UPC. Each row also has the credited artists with their IDs, full-size cover, release date, copyright, genres, track count, explicit rating, audio formats, Apple's notes and its Digital Master badge. Pick the store with country, the US by default.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Album` items (the shared schema, the same on every platform), Apple Music's own chart order (1 = most played). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/applemusic/top_albums/ (Markdown: https://socialtap.dev/docs/reference/applemusic/top_albums/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/applemusic/top_albums/index.md)",
          "url": "https://socialtap.dev/docs/reference/applemusic/top_albums/"
        },
        "operationId": "applemusic.top_albums.list",
        "parameters": [
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store whose chart to read: each has its own. A country with no Apple Music store returns invalid_input. Default: US. UK is read as GB.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "default": "US",
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store whose chart to read: each has its own. A country with no Apple Music store returns invalid_input. Default: US. UK is read as GB.",
              "examples": [
                "JP"
              ],
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the store's own language.",
            "example": "en-US",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the store's own language.",
              "examples": [
                "en-US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "released_at"
                          ],
                          "artist_name": "BigXthaPlug",
                          "artists": [
                            {
                              "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/2d/37/2e/2d372ebd-cf1a-b1f5-2e2e-b8aebb430cf2/ami_U003aidentity_U003a8cd8358dbec0e6453567ddb7d3121e91-2026-10-09T12-14-49.366Z_cropped.png/871x871bb.jpg",
                              "display_name": "BigXthaPlug",
                              "id": "1482508209",
                              "is_verified": null,
                              "url": "https://music.apple.com/us/artist/bigxthaplug/1482508209",
                              "username": null
                            }
                          ],
                          "copyrights": [
                            {
                              "text": "℗ 2026 BigXthaPlug under exclusive license to UnitedMasters LLC",
                              "type": "p"
                            }
                          ],
                          "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/f2/30/e2/f230e2c5-8527-184a-12f7-442f85567061/711209295424.png/3000x3000bb.jpg",
                          "description": "On his previous album, 2025’s I Hope You’re Happy, the irrepressible Dallas rapper BigXthaPlug took a break from being the torchbearer for Texas storytelling rap and reinvented himself as a brokenhearted country crooner. That record was BigX’s highest-charting album to date, but …",
                          "duration_ms": null,
                          "genres": [
                            "Hip-Hop/Rap"
                          ],
                          "id": "6827763091",
                          "is_explicit": true,
                          "label": "BigXthaPlug under exclusive license to UnitedMasters LLC",
                          "metrics": {
                            "track_count": 19
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "audio_traits": [
                                "atmos",
                                "lossless",
                                "lossy-stereo"
                              ],
                              "content_rating": "explicit",
                              "editorial_summary": "The Dallas MC returns to his Southern rap roots.",
                              "is_complete": true,
                              "is_mastered_for_itunes": false,
                              "is_prerelease": false,
                              "more_by_artist": [],
                              "other_versions": [],
                              "rank": 1,
                              "storefront": "us"
                            }
                          },
                          "released_at": "2026-11-02T00:00:00Z",
                          "title": "BETTER OVER TIME",
                          "tracks": [],
                          "type": "album",
                          "unknown_fields": [
                            "tracks",
                            "tracks[].artists",
                            "platform_specific.applemusic.more_by_artist"
                          ],
                          "upc": "711209295424",
                          "url": "https://music.apple.com/us/album/better-over-time/6827763091"
                        },
                        {
                          "approximate_fields": [
                            "released_at"
                          ],
                          "artist_name": "Drake",
                          "artists": [
                            {
                              "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages112/v4/1b/71/65/1b716513-b0c1-9c6b-45aa-cbb9198248cc/01607cf1-1d52-43d2-84ce-d6fc1f4a3475_ami-identity-7665599cc626d803af7956b3691905e7-2022-11-30T21-07-19.526Z_cropped.png/1825x1825bb.jpg",
                              "display_name": "Drake",
                              "id": "271256",
                              "is_verified": null,
                              "url": "https://music.apple.com/us/artist/drake/271256",
                              "username": null
                            }
                          ],
                          "copyrights": [
                            {
                              "text": "℗ 2026 OVO, under exclusive license to Republic Records, a division of UMG Recordings, Inc.",
                              "type": "p"
                            }
                          ],
                          "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/bb/45/62/bb4562a3-45a2-539c-b557-a18ea060a476/26UMGIM63616.rgb.jpg/4500x4500bb.jpg",
                          "description": "& other nicknames I call my dear city",
                          "duration_ms": null,
                          "genres": [
                            "R&B/Soul"
                          ],
                          "id": "6818209777",
                          "is_explicit": true,
                          "label": "OVO/Republic",
                          "metrics": {
                            "track_count": 24
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "audio_traits": [
                                "lossless",
                                "lossy-stereo"
                              ],
                              "content_rating": "explicit",
                              "editorial_summary": "The 2026 album, now with videos and four previously unreleased tracks.",
                              "is_complete": true,
                              "is_mastered_for_itunes": true,
                              "is_prerelease": false,
                              "more_by_artist": [],
                              "other_versions": [],
                              "rank": 2,
                              "storefront": "us"
                            }
                          },
                          "released_at": "2026-10-02T00:00:00Z",
                          "title": "HABIBTI (FOMO)",
                          "tracks": [],
                          "type": "album",
                          "unknown_fields": [
                            "tracks",
                            "tracks[].artists",
                            "platform_specific.applemusic.more_by_artist"
                          ],
                          "upc": "00881061707059",
                          "url": "https://music.apple.com/us/album/habibti-fomo/6818209777"
                        },
                        {
                          "approximate_fields": [
                            "released_at"
                          ],
                          "artist_name": "Olivia Rodrigo",
                          "artists": [
                            {
                              "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/ba/36/7a/ba367a61-9f8a-8905-9dbd-7a99db6ee77b/ami-identity-5b05d351a6e3c7256ef7680c8aef2894-2026-06-12T04-01-34.107Z_cropped.png/972x972bb.jpg",
                              "display_name": "Olivia Rodrigo",
                              "id": "979458609",
                              "is_verified": null,
                              "url": "https://music.apple.com/us/artist/olivia-rodrigo/979458609",
                              "username": null
                            }
                          ],
                          "copyrights": [
                            {
                              "text": "℗ 2026 Olivia Rodrigo, under exclusive license to Geffen Records",
                              "type": "p"
                            }
                          ],
                          "cover_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/1d/1b/f9/1d1bf9b1-44c6-9a6c-6ffb-c158488c06ce/26UMGIM39303.rgb.jpg/4000x4000bb.jpg",
                          "description": "A pop savant raises her game and her standards on her third album. Olivia Rodrigo has loved and lost many times since she cried through the suburbs as the heartbroken teenager in “drivers license.” She’s grown up, and her standards have gotten higher—for a good love song, but als…",
                          "duration_ms": null,
                          "genres": [
                            "Pop"
                          ],
                          "id": "1889992111",
                          "is_explicit": true,
                          "label": "Olivia Rodrigo PS",
                          "metrics": {
                            "track_count": 14
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "audio_traits": [
                                "atmos",
                                "lossless",
                                "lossy-stereo"
                              ],
                              "content_rating": "explicit",
                              "editorial_summary": "A pop savant raises her game and her standards on her third album.",
                              "is_complete": true,
                              "is_mastered_for_itunes": true,
                              "is_prerelease": false,
                              "more_by_artist": [],
                              "other_versions": [],
                              "rank": 3,
                              "storefront": "us"
                            }
                          },
                          "released_at": "2026-06-12T00:00:00Z",
                          "title": "you seem pretty sad for a girl so in love",
                          "tracks": [],
                          "type": "album",
                          "unknown_fields": [
                            "tracks",
                            "tracks[].artists",
                            "platform_specific.applemusic.more_by_artist"
                          ],
                          "upc": "00199957777902",
                          "url": "https://music.apple.com/us/album/you-seem-pretty-sad-for-a-girl-so-in-love/1889992111"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "applemusic",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 336,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ApplemusicTop_albumsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Most played albums chart by country",
        "tags": [
          "Apple Music"
        ],
        "x-socialtap-endpoint": "applemusic.top_albums",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Apple Music's own chart order (1 = most played)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "album",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/applemusic/top_playlists": {
      "get": {
        "description": "Returns Apple Music's chart of the most played playlists in a country's store, top first, a page at a time, with each playlist's rank and curator. Each row also has the title, Apple's description and note, full-size cover, track count, whether Apple's editors or an outside curator make it, when it last changed and its audio formats. Pick the store with country, the US by default.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Playlist` items (the shared schema, the same on every platform), Apple Music's own chart order (1 = most played). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/applemusic/top_playlists/ (Markdown: https://socialtap.dev/docs/reference/applemusic/top_playlists/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/applemusic/top_playlists/index.md)",
          "url": "https://socialtap.dev/docs/reference/applemusic/top_playlists/"
        },
        "operationId": "applemusic.top_playlists.list",
        "parameters": [
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store whose chart to read: each has its own. A country with no Apple Music store returns invalid_input. Default: US. UK is read as GB.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "default": "US",
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store whose chart to read: each has its own. A country with no Apple Music store returns invalid_input. Default: US. UK is read as GB.",
              "examples": [
                "JP"
              ],
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the store's own language.",
            "example": "en-US",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the store's own language.",
              "examples": [
                "en-US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "description": "Music has been an essential part of any holiday celebration for centuries. This playlist honors that history, collecting old chestnuts, new classics, and future sing-along staples to soundtrack your next Christmas. Trim the tree, open the presents, and serve up some eggnog as pop…",
                          "id": "pl.b0e04e25887741ea845e1d5c88397fd4",
                          "is_collaborative": false,
                          "metrics": {
                            "post_count": 100
                          },
                          "owner": {
                            "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/Features126/v4/dc/03/16/dc031679-6f1e-5ec0-cd81-17edf19c66c2/7e2c3f93-9d73-41c2-9cec-841a2240173a.png/1080x1080bb.jpg",
                            "display_name": "Holiday",
                            "id": null,
                            "is_verified": null,
                            "url": "https://music.apple.com/us/curator/holiday/976439540",
                            "username": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "audio_traits": [],
                              "band": null,
                              "curator_id": "976439540",
                              "editorial_kind": null,
                              "editorial_sub_kind": null,
                              "editorial_summary": "The songs that define the season.",
                              "frequency": null,
                              "is_chart": false,
                              "is_collaborative": false,
                              "is_live": null,
                              "is_subscription_required": null,
                              "last_modified_at": "2026-10-23T19:16:13Z",
                              "media_kind": null,
                              "playlist_type": "editorial",
                              "rank": 1,
                              "station_kind": null,
                              "storefront": "us"
                            }
                          },
                          "platform_type": "playlist",
                          "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Features112/v4/d1/a8/45/d1a84579-ce57-5a1f-1334-e6c417605020/befc39eb-584c-4681-92b0-16c913f1230a.png/4320x1080cc.jpg",
                          "title": "Essential Christmas",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://music.apple.com/us/playlist/essential-christmas/pl.b0e04e25887741ea845e1d5c88397fd4"
                        },
                        {
                          "approximate_fields": [],
                          "description": "This playlist tracks what’s happening from the heart of the country scene to its outer edges. Find fan favorites you already love next to breakout stars and emerging voices. Topping the list this week is HARDY with “By God,” a track off the country star’s just-released EP Sides. …",
                          "id": "pl.87bb5b36a9bd49db8c975607452bfa2b",
                          "is_collaborative": false,
                          "metrics": {
                            "post_count": 73
                          },
                          "owner": {
                            "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/Features/v4/a0/3c/32/a03c3207-70b9-5a3d-28d9-430e2a1891cc/2775cb3b-a652-41ea-91f5-e28fe0d43bde.png/1080x1080bb.jpg",
                            "display_name": "Apple Music Country",
                            "id": null,
                            "is_verified": null,
                            "url": "https://music.apple.com/us/curator/apple-music-country/976439534",
                            "username": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "audio_traits": [],
                              "band": null,
                              "curator_id": "976439534",
                              "editorial_kind": null,
                              "editorial_sub_kind": null,
                              "editorial_summary": "“By God” is HARDY at his most inspirational.",
                              "frequency": null,
                              "is_chart": false,
                              "is_collaborative": false,
                              "is_live": null,
                              "is_subscription_required": null,
                              "last_modified_at": "2026-10-30T23:33:21Z",
                              "media_kind": null,
                              "playlist_type": "editorial",
                              "rank": 2,
                              "station_kind": null,
                              "storefront": "us"
                            }
                          },
                          "platform_type": "playlist",
                          "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Features/v4/ea/0a/1d/ea0a1d2e-6b0b-e3b7-673f-2534fb354b22/dd2db469-90b2-4cd7-9c7b-83809965c0f9.png/1080x1080SC.DN02.jpg?l=en-US",
                          "title": "Today’s Country",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://music.apple.com/us/playlist/todays-country/pl.87bb5b36a9bd49db8c975607452bfa2b"
                        },
                        {
                          "approximate_fields": [],
                          "description": "From the alt vanguard to modern vets, straightforward to left-field, R&B Now captures where the genre is now and points the way to where it’s going. In 2026, that meant another breakout year for Kehlani, the moment years of consistent artistry finally converted into mainstream do…",
                          "id": "pl.9987b58cfa9747328b3fe9b974e2b797",
                          "is_collaborative": false,
                          "metrics": {
                            "post_count": 50
                          },
                          "owner": {
                            "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/Features/v4/47/94/31/479431e2-12bd-c03e-48bd-1022fe74b1b2/b8395439-127c-43b1-bea6-ebc3433a0e9c.png/1080x1080bb.jpg",
                            "display_name": "Apple Music R&B",
                            "id": null,
                            "is_verified": null,
                            "url": "https://music.apple.com/us/curator/apple-music-r-b/976439551",
                            "username": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "audio_traits": [],
                              "band": null,
                              "curator_id": "976439551",
                              "editorial_kind": null,
                              "editorial_sub_kind": null,
                              "editorial_summary": "In 2026, Kehlani’s “Folded” told us everything we needed to hear.",
                              "frequency": null,
                              "is_chart": false,
                              "is_collaborative": false,
                              "is_live": null,
                              "is_subscription_required": null,
                              "last_modified_at": "2026-11-04T17:39:22Z",
                              "media_kind": null,
                              "playlist_type": "editorial",
                              "rank": 3,
                              "station_kind": null,
                              "storefront": "us"
                            }
                          },
                          "platform_type": "playlist",
                          "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Features/v4/59/98/c9/5998c9a4-61d1-c40a-c790-f525acc95b40/4b4be703-911f-4917-8199-12762b25551d.png/1080x1080SC.DN02.jpg?l=en-US",
                          "title": "R&B Now: Best of 2026",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://music.apple.com/us/playlist/r-b-now-best-of-2026/pl.9987b58cfa9747328b3fe9b974e2b797"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "applemusic",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 384,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ApplemusicTop_playlistsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Most played playlists chart by country",
        "tags": [
          "Apple Music"
        ],
        "x-socialtap-endpoint": "applemusic.top_playlists",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Apple Music's own chart order (1 = most played)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "playlist",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/applemusic/top_tracks": {
      "get": {
        "description": "Returns Apple Music's chart of the most played songs or music videos in a country's store, top first, a page at a time, with each one's rank and ISRC. Each row also has the credited artists with their IDs, album, length, release date, composer, genres, explicit rating, audio formats, whether Apple has its lyrics, artwork and a preview clip. Pick the store with country and the chart with kind: the US songs chart by default.\n\nReturns `{data, page, meta}`: `data` holds up to 100 `Post` items (Apple Music calls it a track) (the shared schema, the same on every platform), Apple Music's own chart order (1 = most played). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/applemusic/top_tracks/ (Markdown: https://socialtap.dev/docs/reference/applemusic/top_tracks/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/applemusic/top_tracks/index.md)",
          "url": "https://socialtap.dev/docs/reference/applemusic/top_tracks/"
        },
        "operationId": "applemusic.top_tracks.list",
        "parameters": [
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store whose chart to read: each has its own. A country with no Apple Music store returns invalid_input. Default: US. UK is read as GB.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "default": "US",
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store whose chart to read: each has its own. A country with no Apple Music store returns invalid_input. Default: US. UK is read as GB.",
              "examples": [
                "JP"
              ],
              "type": "string"
            }
          },
          {
            "description": "Which chart: most played songs (the default) or music videos. Both come back in the same post shape, and platform_type says which it is.",
            "example": "song",
            "in": "query",
            "name": "kind",
            "schema": {
              "default": "song",
              "description": "Which chart: most played songs (the default) or music videos. Both come back in the same post shape, and platform_type says which it is.",
              "enum": [
                "song",
                "music_video"
              ],
              "examples": [
                "music_video"
              ],
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the store's own language.",
            "example": "en-US",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the store's own language.",
              "examples": [
                "en-US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 100,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages211/v4/7d/f9/5b/7df95b8e-26fb-5e14-f35d-f603abc52dc8/ami-identity-6b9f829473ca41446a842ac18b0e65ee-2026-01-27T17-02-20.725Z_cropped.png/2400x2400bb.jpg",
                            "display_name": "Ella Langley",
                            "id": "1384373733",
                            "is_verified": null,
                            "url": "https://music.apple.com/us/artist/ella-langley/1384373733",
                            "username": null
                          },
                          "coauthors": [],
                          "duration_ms": 232226,
                          "hashtags": [],
                          "id": "1844932150",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/e2/91/4d/e2914d0a-7f1d-f04c-fbf4-c50b38548838/196873638690.jpg/3000x3000bb.jpg",
                              "type": "audio",
                              "url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview211/v4/38/49/4c/38494cb4-f9e0-1db4-0b84-8c478cb55390/mzaf_14015374052766148372.plus.aac.ep.m4a",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "air_ended_at": null,
                              "album_artist_name": "Ella Langley",
                              "album_id": "1844932149",
                              "album_title": "Choosin' Texas - Single",
                              "album_url": "https://music.apple.com/us/album/choosin-texas-single/1844932149",
                              "artist_name": "Ella Langley",
                              "attribution": null,
                              "audio_locale": "en-US",
                              "audio_traits": [
                                "atmos",
                                "lossless",
                                "lossy-stereo"
                              ],
                              "composer_name": "Ella Langley, Luke Dick, Miranda Lambert & Joybeth Taylor",
                              "content_rating": null,
                              "curator_id": null,
                              "disc_number": 1,
                              "genres": [
                                "Country"
                              ],
                              "is_4k": null,
                              "is_apple_digital_master": false,
                              "is_explicit": false,
                              "is_hdr": null,
                              "is_live": null,
                              "is_lyrics_available": true,
                              "is_mastered_for_itunes": false,
                              "is_time_synced_lyrics_available": true,
                              "isrc": "USSM12504190",
                              "long_note": null,
                              "movement_count": null,
                              "movement_name": null,
                              "movement_number": null,
                              "rank": 1,
                              "storefront": "us",
                              "track_number": 1,
                              "video_traits": [],
                              "work_name": null
                            }
                          },
                          "platform_type": "song",
                          "published_at": "2025-10-17T00:00:00Z",
                          "text": null,
                          "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/e2/91/4d/e2914d0a-7f1d-f04c-fbf4-c50b38548838/196873638690.jpg/3000x3000bb.jpg",
                          "title": "Choosin' Texas",
                          "type": "audio",
                          "unknown_fields": [],
                          "url": "https://music.apple.com/us/album/choosin-texas/1844932149?i=1844932150"
                        },
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/84/8a/4e/848a4e8b-48c7-e3fa-ae20-a42cd4b469a8/ami-identity-d59cbd95617167e768f2dbfe6377cf2e-2026-08-09T23-03-10.005Z_cropped.png/1454x1454bb.jpg",
                            "display_name": "KAROL G",
                            "id": "290814601",
                            "is_verified": null,
                            "url": "https://music.apple.com/us/artist/karol-g/290814601",
                            "username": null
                          },
                          "coauthors": [
                            {
                              "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/f2/bd/40/f2bd40bd-cbc0-bb7d-87b2-27f8b2eed765/ami-identity-7f43d3c2d6a3b0cb7b4be17c4fd5aca6-2024-10-24T17-10-43.339Z_cropped.png/1349x1349bb.jpg",
                              "display_name": "Judeline",
                              "id": "1487503245",
                              "is_verified": null,
                              "url": "https://music.apple.com/us/artist/judeline/1487503245",
                              "username": null
                            },
                            {
                              "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/7f/72/61/7f7261cb-880d-6bf2-73e7-07107d3764c4/file_cropped.png/1830x1830bb.jpg",
                              "display_name": "rusowsky",
                              "id": "1388592825",
                              "is_verified": null,
                              "url": "https://music.apple.com/us/artist/rusowsky/1388592825",
                              "username": null
                            }
                          ],
                          "duration_ms": 225835,
                          "hashtags": [],
                          "id": "6796864754",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/2b/66/b2/2b66b26c-ab23-faa1-c4ee-06fa2cce8f76/26UM1IM00558.rgb.jpg/3000x3000bb.jpg",
                              "type": "audio",
                              "url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/f3/08/da/f308da3d-00cc-7682-7be9-87cb882f4ea5/mzaf_14078178240008272749.plus.aac.ep.m4a",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "air_ended_at": null,
                              "album_artist_name": "KAROL G",
                              "album_id": "6796864741",
                              "album_title": "NO ME ARREPIENTO DE SENTIR TANTO",
                              "album_url": "https://music.apple.com/us/album/no-me-arrepiento-de-sentir-tanto/6796864741",
                              "artist_name": "KAROL G, Judeline & rusowsky",
                              "attribution": null,
                              "audio_locale": "es-ES",
                              "audio_traits": [
                                "atmos",
                                "lossless",
                                "lossy-stereo"
                              ],
                              "composer_name": "Cordel Dexter Burrell, Carolina Giraldo Navarro, Marco Masis, Omer Fedi, Lara Fernández Castrelo, Andres Jael Correa Rios & Ruslán Mediavilla",
                              "content_rating": null,
                              "curator_id": null,
                              "disc_number": 1,
                              "genres": [
                                "Urbano latino",
                                "Latin"
                              ],
                              "is_4k": null,
                              "is_apple_digital_master": true,
                              "is_explicit": false,
                              "is_hdr": null,
                              "is_live": null,
                              "is_lyrics_available": true,
                              "is_mastered_for_itunes": true,
                              "is_time_synced_lyrics_available": true,
                              "isrc": "USUG12607940",
                              "long_note": null,
                              "movement_count": null,
                              "movement_name": null,
                              "movement_number": null,
                              "rank": 2,
                              "storefront": "us",
                              "track_number": 11,
                              "video_traits": [],
                              "work_name": null
                            }
                          },
                          "platform_type": "song",
                          "published_at": "2026-08-05T00:00:00Z",
                          "text": null,
                          "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/2b/66/b2/2b66b26c-ab23-faa1-c4ee-06fa2cce8f76/26UM1IM00558.rgb.jpg/3000x3000bb.jpg",
                          "title": "BbY WOW",
                          "type": "audio",
                          "unknown_fields": [],
                          "url": "https://music.apple.com/us/album/bby-wow/6796864741?i=6796864754"
                        },
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages211/v4/19/7a/a7/197aa7f2-53af-5777-72ed-e292b550d159/ami_U003aidentity_U003a11b6c33ddb521791b7ba1dd8c4dcf764-2026-10-16T00-09-37.146Z_cropped.png/902x902bb.jpg",
                            "display_name": "Tate McRae",
                            "id": "1446365464",
                            "is_verified": null,
                            "url": "https://music.apple.com/us/artist/tate-mcrae/1446365464",
                            "username": null
                          },
                          "coauthors": [],
                          "duration_ms": 208810,
                          "hashtags": [],
                          "id": "6822497774",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/69/64/e4/6964e483-c02c-e389-14f4-c426e8c65f2c/196874840146.jpg/3000x3000bb.jpg",
                              "type": "audio",
                              "url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/05/27/d4/0527d4f3-f6af-1ef8-6a32-25477b7b00ba/mzaf_9026536433413395761.plus.aac.ep.m4a",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "applemusic",
                          "platform_specific": {
                            "applemusic": {
                              "air_ended_at": null,
                              "album_artist_name": "Tate McRae",
                              "album_id": "6822497770",
                              "album_title": "Housewife - Single",
                              "album_url": "https://music.apple.com/us/album/housewife-single/6822497770",
                              "artist_name": "Tate McRae",
                              "attribution": null,
                              "audio_locale": "en-US",
                              "audio_traits": [
                                "atmos",
                                "lossless",
                                "lossy-stereo"
                              ],
                              "composer_name": "Tate McRae, Julia Michaels, Ryan Tedder, Grant Boutin, Jasper Harris & Pablo Diaz-Reixa",
                              "content_rating": null,
                              "curator_id": null,
                              "disc_number": 1,
                              "genres": [
                                "Pop"
                              ],
                              "is_4k": null,
                              "is_apple_digital_master": false,
                              "is_explicit": false,
                              "is_hdr": null,
                              "is_live": null,
                              "is_lyrics_available": true,
                              "is_mastered_for_itunes": false,
                              "is_time_synced_lyrics_available": true,
                              "isrc": "USRC12601916",
                              "long_note": null,
                              "movement_count": null,
                              "movement_name": null,
                              "movement_number": null,
                              "rank": 3,
                              "storefront": "us",
                              "track_number": 1,
                              "video_traits": [],
                              "work_name": null
                            }
                          },
                          "platform_type": "song",
                          "published_at": "2026-10-15T00:00:00Z",
                          "text": null,
                          "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/69/64/e4/6964e483-c02c-e389-14f4-c426e8c65f2c/196874840146.jpg/3000x3000bb.jpg",
                          "title": "Housewife",
                          "type": "audio",
                          "unknown_fields": [],
                          "url": "https://music.apple.com/us/album/housewife/6822497770?i=6822497774"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "applemusic",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 488,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ApplemusicTop_tracksResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Most played songs and music videos by country",
        "tags": [
          "Apple Music"
        ],
        "x-socialtap-endpoint": "applemusic.top_tracks",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Apple Music's own chart order (1 = most played)",
          "page_max": 100,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/applemusic/track": {
      "get": {
        "description": "Returns an Apple Music song, music video or radio episode from its link or ID in any country's store, with its ISRC, composer and audio formats. It also has the artists, album, disc and track number, exact length, release date, genres, explicit rating, whether Apple has its lyrics, the classical work and movement, artwork and a preview clip. Legacy iTunes links work too.\n\nReturns `{data, meta}`: `data` is a `Post` object (Apple Music calls it a track) (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/applemusic/track/ (Markdown: https://socialtap.dev/docs/reference/applemusic/track/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/applemusic/track/index.md)",
          "url": "https://socialtap.dev/docs/reference/applemusic/track/"
        },
        "operationId": "applemusic.track.get",
        "parameters": [
          {
            "description": "The track: its album link with ?i= (music.apple.com/us/album/lover/1468058165?i=1468058169), its song link (music.apple.com/us/song/i-forgot-that-you-existed/1468058169), a music video's link (music.apple.com/us/music-video/hello/1544490140), a radio episode's link (music.apple.com/us/station/20-years-of-taylor-swift/ra.6825008805), with or without the slug and the store, on music.apple.com, geo.music.apple.com or itunes.apple.com; or its ID alone (1468058169, ra.6825008805).",
            "example": "https://music.apple.com/us/album/lover/1468058165?i=1468058169",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The track: its album link with ?i= (music.apple.com/us/album/lover/1468058165?i=1468058169), its song link (music.apple.com/us/song/i-forgot-that-you-existed/1468058169), a music video's link (music.apple.com/us/music-video/hello/1544490140), a radio episode's link (music.apple.com/us/station/20-years-of-taylor-swift/ra.6825008805), with or without the slug and the store, on music.apple.com, geo.music.apple.com or itunes.apple.com; or its ID alone (1468058169, ra.6825008805).",
              "examples": [
                "https://music.apple.com/us/album/lover/1468058165?i=1468058169"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store to read: the same ID has its own title language, availability and links per store. Default: the store in the link, else us.",
            "example": "us",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The Apple Music store to read: the same ID has its own title language, availability and links per store. Default: the store in the link, else us.",
              "examples": [
                "us"
              ],
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the link's l=, else the store's own language.",
            "example": "en-US",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's text, when Apple offers it beside the store's own. Default: the link's l=, else the store's own language.",
              "examples": [
                "en-US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "published_at"
                        ],
                        "author": {
                          "avatar_url": "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/6d/67/88/6d67888b-9e7f-53af-7853-0f91d6fd2332/ami_U003aidentity_U003a994af5c375f4c3aa96cd6ced4a700799-2026-09-25T04-00-05.358Z_cropped.png/1640x1640bb.jpg",
                          "display_name": "Taylor Swift",
                          "id": "159260351",
                          "is_verified": null,
                          "url": "https://music.apple.com/us/artist/taylor-swift/159260351",
                          "username": null
                        },
                        "coauthors": [],
                        "duration_ms": 170651,
                        "hashtags": [],
                        "id": "1468058169",
                        "is_nsfw": null,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": null,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": null,
                            "expires_at": null,
                            "height": null,
                            "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Music125/v4/49/3d/ab/493dab54-f920-9043-6181-80993b8116c9/19UMGIM53909.rgb.jpg/3900x3900bb.jpg",
                            "type": "audio",
                            "url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/9c/e2/97/9ce2976a-b1c8-aa80-3e94-f4562cbad53e/mzaf_13898706762824220632.plus.aac.ep.m4a",
                            "width": null
                          }
                        ],
                        "mentions": [],
                        "metrics": {
                          "comment_count": null,
                          "like_count": null,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": null,
                          "share_count": null,
                          "view_count": null
                        },
                        "platform": "applemusic",
                        "platform_specific": {
                          "applemusic": {
                            "air_ended_at": null,
                            "album_artist_name": "Taylor Swift",
                            "album_id": "1468058165",
                            "album_title": "Lover",
                            "album_url": "https://music.apple.com/us/album/lover/1468058165",
                            "artist_name": "Taylor Swift",
                            "attribution": null,
                            "audio_locale": "en-US",
                            "audio_traits": [
                              "atmos",
                              "lossless",
                              "lossy-stereo"
                            ],
                            "composer_name": "Taylor Swift, Louis Bell & Adam Feeney",
                            "content_rating": null,
                            "curator_id": null,
                            "disc_number": 1,
                            "genres": [
                              "Pop"
                            ],
                            "is_4k": null,
                            "is_apple_digital_master": true,
                            "is_explicit": false,
                            "is_hdr": null,
                            "is_live": null,
                            "is_lyrics_available": true,
                            "is_mastered_for_itunes": true,
                            "is_time_synced_lyrics_available": true,
                            "isrc": "USUG11901471",
                            "long_note": null,
                            "movement_count": null,
                            "movement_name": null,
                            "movement_number": null,
                            "rank": null,
                            "storefront": "us",
                            "track_number": 1,
                            "video_traits": [],
                            "work_name": null
                          }
                        },
                        "platform_type": "song",
                        "published_at": "2019-08-23T00:00:00Z",
                        "text": null,
                        "thumbnail_url": "https://is1-ssl.mzstatic.com/image/thumb/Music125/v4/49/3d/ab/493dab54-f920-9043-6181-80993b8116c9/19UMGIM53909.rgb.jpg/3900x3900bb.jpg",
                        "title": "I Forgot That You Existed",
                        "type": "audio",
                        "unknown_fields": [],
                        "url": "https://music.apple.com/us/album/i-forgot-that-you-existed/1468058165?i=1468058169"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "applemusic",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 154,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "1468058169",
                          "url": "https://music.apple.com/us/album/i-forgot-that-you-existed/1468058165?i=1468058169"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ApplemusicTrackResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Song with ISRC, composer and audio formats",
        "tags": [
          "Apple Music"
        ],
        "x-socialtap-endpoint": "applemusic.track",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/billing/auto_topup": {
      "get": {
        "description": "The account's auto top-up: the pack it buys when the balance falls to its threshold, its monthly cap and what it charged this month, the saved card it charges, its latest top-up, and why it turned itself off, if it did. Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "billing.auto_topup.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "currency": {
                          "description": "The currency of the amounts (ISO 4217).",
                          "enum": [
                            "usd"
                          ],
                          "type": "string"
                        },
                        "enabled": {
                          "description": "Whether a balance falling to threshold buys pack now.",
                          "type": "boolean"
                        },
                        "last_charge": {
                          "description": "The latest top-up, whatever its outcome; null before the first.",
                          "properties": {
                            "amount_tax": {
                              "description": "The tax in amount_total (Stripe Tax: only where SocialTap collects it); null when amount_total is.",
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "amount_total": {
                              "description": "Charged, tax included, in cents of currency; null when nothing was charged or before it is known.",
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "created_at": {
                              "description": "When the balance crossed the threshold, RFC 3339 UTC.",
                              "format": "date-time",
                              "type": "string"
                            },
                            "credits": {
                              "description": "Credits the pack adds.",
                              "type": "integer"
                            },
                            "currency": {
                              "description": "amount_total's currency (ISO 4217).",
                              "enum": [
                                "usd"
                              ],
                              "type": "string"
                            },
                            "id": {
                              "description": "Top-up ID (atu_…): the ref of its credit_transaction, and on the Stripe payment's metadata.",
                              "type": "string"
                            },
                            "message": {
                              "description": "What the bank or Stripe said, for people; null when reason is.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "object": {
                              "description": "Always auto_topup_charge.",
                              "enum": [
                                "auto_topup_charge"
                              ],
                              "type": "string"
                            },
                            "pack": {
                              "description": "The credit pack (catalog pack ID).",
                              "type": "string"
                            },
                            "reason": {
                              "description": "Why it failed (the off_reason it set) or was skipped (monthly_cap, trust_limit: it would have passed rolling_limit_cents); null otherwise.",
                              "enum": [
                                "card_declined",
                                "authentication_required",
                                "no_card",
                                "billing_address_required",
                                "payment_failed",
                                "disputed",
                                "monthly_cap",
                                "trust_limit"
                              ],
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "status": {
                              "description": "processing (the charge is under way), succeeded (paid: its credits were added, once), failed (nothing charged: auto top-up turned off, see reason) or skipped (it would have passed the monthly cap or the 7-day limit: nothing charged, auto top-up stays on).",
                              "enum": [
                                "processing",
                                "succeeded",
                                "failed",
                                "skipped"
                              ],
                              "type": "string"
                            }
                          },
                          "required": [
                            "object",
                            "id",
                            "status",
                            "pack",
                            "credits",
                            "amount_total",
                            "amount_tax",
                            "currency",
                            "reason",
                            "message",
                            "created_at"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "month_resets_at": {
                          "description": "Start of the next calendar month (UTC), when spent_this_month_cents starts again from 0.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "monthly_cap_cents": {
                          "description": "The most auto top-up charges in a calendar month (UTC), tax included, in cents of currency; a top-up that would pass it does not run (the owner is emailed). null until set up.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "notice": {
                          "description": "What a person should know about the change just made, in a sentence to show them: the chosen pack can't run under rolling_limit_cents, say, so it will be skipped. It never refuses the change. Null otherwise, and on every read.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "object": {
                          "description": "Always auto_topup.",
                          "enum": [
                            "auto_topup"
                          ],
                          "type": "string"
                        },
                        "off_at": {
                          "description": "When it turned itself off, RFC 3339 UTC; null when off_reason is.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "off_message": {
                          "description": "What the bank or Stripe said, for people; null when off_reason is.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "off_reason": {
                          "description": "Why auto top-up turned itself off (null while on, or when a person turned it off): card_declined (the bank declined the charge), authentication_required (the bank asked the cardholder to confirm it: buy the pack in Billing, then turn auto top-up back on), no_card (no saved card), billing_address_required (Stripe Tax needs the card's billing address: add it in the payment settings), payment_failed (another payment error), disputed (a payment on this account was disputed: auto top-up turns on again only with a different card), bank_inquiry (a bank asked about a payment on this account, which is not yet a dispute: turn it back on when you are ready), plan_ended (it bought a monthly plan's top-up, and the plan ended). It never retries: fix the cause, then turn it on again.",
                          "enum": [
                            "card_declined",
                            "authentication_required",
                            "no_card",
                            "billing_address_required",
                            "payment_failed",
                            "disputed",
                            "bank_inquiry",
                            "plan_ended"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "pack": {
                          "description": "The credit pack each top-up buys (catalog pack ID); null until auto top-up is first set up.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "payment_method": {
                          "description": "The saved card a top-up charges (the default card in the payment settings, else the newest); null when there is none, or when the payment processor could not be reached.",
                          "properties": {
                            "brand": {
                              "description": "Card brand (visa, mastercard, amex, …).",
                              "type": "string"
                            },
                            "exp_month": {
                              "description": "Expiry month (1–12).",
                              "type": "integer"
                            },
                            "exp_year": {
                              "description": "Expiry year.",
                              "type": "integer"
                            },
                            "last4": {
                              "description": "The card number's last four digits.",
                              "type": "string"
                            }
                          },
                          "required": [
                            "brand",
                            "last4",
                            "exp_month",
                            "exp_year"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "rolling_limit_cents": {
                          "description": "The most auto top-up charges in any 7 days, tax included, in cents, whatever monthly_cap_cents says: it grows with the payments that settled on this account, and support can lift it. A top-up that would pass it does not run (the owner is emailed); buying a pack by hand is never limited by it.",
                          "type": "integer"
                        },
                        "rolling_spent_cents": {
                          "description": "What auto top-up charged in the last 7 days, tax included, counting a charge in progress, in cents.",
                          "type": "integer"
                        },
                        "spent_this_month_cents": {
                          "description": "What auto top-up charged this calendar month, tax included, counting a charge in progress, in cents.",
                          "type": "integer"
                        },
                        "threshold": {
                          "description": "Credits: a balance change that leaves the balance at or below this buys the pack, once until the balance is above it again. null until set up.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "object",
                        "enabled",
                        "pack",
                        "threshold",
                        "monthly_cap_cents",
                        "currency",
                        "spent_this_month_cents",
                        "rolling_limit_cents",
                        "rolling_spent_cents",
                        "month_resets_at",
                        "off_reason",
                        "off_message",
                        "off_at",
                        "payment_method",
                        "last_charge",
                        "notice"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get auto top-up",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Get auto top-up",
        "tags": [
          "Billing"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "patch": {
        "description": "Auto top-up buys `pack` with the account's saved card (off-session; sales tax added where SocialTap collects it, as at checkout) whenever a balance change leaves the balance at or below `threshold`, one top-up at a time, never past `monthly_cap_cents` in a calendar month (UTC), tax included (by default `default_cap_packs` (3) × the pack's price). A charge that fails is never retried: auto top-up turns off, the owner is emailed why, and a person turns it back on once the card is fixed. A top-up that would pass `rolling_limit_cents` in any 7 days is skipped, the owner is told how to lift it, it runs by itself once there is room, and `notice` says so when the chosen pack is already past it. A dispute of any payment on the account turns it off, and it turns on again only with a different card; a bank's inquiry only turns it off. The owner is emailed when anyone else turns it on or raises its cap. The dashboard session only, with a fresh sign-in: it authorizes charges to the card. Absent fields keep their value. Free.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "billing.auto_topup.update",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "enabled": {
                    "description": "true turns auto top-up on: it needs a saved card (not one disputed on this account), a pack and a threshold (the low-balance alert's when left out), and sets monthly_cap_cents to 3 × the pack's price when none was set. A balance already at or below the threshold buys the pack at the next request. false turns it off; nothing in progress is canceled.",
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "monthly_cap_cents": {
                    "description": "Cents; at least the pack's price (or no top-up could run).",
                    "maximum": 10000000,
                    "minimum": 1,
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "pack": {
                    "description": "A credit pack ID of the catalog (packs).",
                    "maxLength": 20,
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "threshold": {
                    "description": "Credits.",
                    "maximum": 1000000000,
                    "minimum": 0,
                    "type": [
                      "integer",
                      "null"
                    ]
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "currency": {
                          "description": "The currency of the amounts (ISO 4217).",
                          "enum": [
                            "usd"
                          ],
                          "type": "string"
                        },
                        "enabled": {
                          "description": "Whether a balance falling to threshold buys pack now.",
                          "type": "boolean"
                        },
                        "last_charge": {
                          "description": "The latest top-up, whatever its outcome; null before the first.",
                          "properties": {
                            "amount_tax": {
                              "description": "The tax in amount_total (Stripe Tax: only where SocialTap collects it); null when amount_total is.",
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "amount_total": {
                              "description": "Charged, tax included, in cents of currency; null when nothing was charged or before it is known.",
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "created_at": {
                              "description": "When the balance crossed the threshold, RFC 3339 UTC.",
                              "format": "date-time",
                              "type": "string"
                            },
                            "credits": {
                              "description": "Credits the pack adds.",
                              "type": "integer"
                            },
                            "currency": {
                              "description": "amount_total's currency (ISO 4217).",
                              "enum": [
                                "usd"
                              ],
                              "type": "string"
                            },
                            "id": {
                              "description": "Top-up ID (atu_…): the ref of its credit_transaction, and on the Stripe payment's metadata.",
                              "type": "string"
                            },
                            "message": {
                              "description": "What the bank or Stripe said, for people; null when reason is.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "object": {
                              "description": "Always auto_topup_charge.",
                              "enum": [
                                "auto_topup_charge"
                              ],
                              "type": "string"
                            },
                            "pack": {
                              "description": "The credit pack (catalog pack ID).",
                              "type": "string"
                            },
                            "reason": {
                              "description": "Why it failed (the off_reason it set) or was skipped (monthly_cap, trust_limit: it would have passed rolling_limit_cents); null otherwise.",
                              "enum": [
                                "card_declined",
                                "authentication_required",
                                "no_card",
                                "billing_address_required",
                                "payment_failed",
                                "disputed",
                                "monthly_cap",
                                "trust_limit"
                              ],
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "status": {
                              "description": "processing (the charge is under way), succeeded (paid: its credits were added, once), failed (nothing charged: auto top-up turned off, see reason) or skipped (it would have passed the monthly cap or the 7-day limit: nothing charged, auto top-up stays on).",
                              "enum": [
                                "processing",
                                "succeeded",
                                "failed",
                                "skipped"
                              ],
                              "type": "string"
                            }
                          },
                          "required": [
                            "object",
                            "id",
                            "status",
                            "pack",
                            "credits",
                            "amount_total",
                            "amount_tax",
                            "currency",
                            "reason",
                            "message",
                            "created_at"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "month_resets_at": {
                          "description": "Start of the next calendar month (UTC), when spent_this_month_cents starts again from 0.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "monthly_cap_cents": {
                          "description": "The most auto top-up charges in a calendar month (UTC), tax included, in cents of currency; a top-up that would pass it does not run (the owner is emailed). null until set up.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "notice": {
                          "description": "What a person should know about the change just made, in a sentence to show them: the chosen pack can't run under rolling_limit_cents, say, so it will be skipped. It never refuses the change. Null otherwise, and on every read.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "object": {
                          "description": "Always auto_topup.",
                          "enum": [
                            "auto_topup"
                          ],
                          "type": "string"
                        },
                        "off_at": {
                          "description": "When it turned itself off, RFC 3339 UTC; null when off_reason is.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "off_message": {
                          "description": "What the bank or Stripe said, for people; null when off_reason is.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "off_reason": {
                          "description": "Why auto top-up turned itself off (null while on, or when a person turned it off): card_declined (the bank declined the charge), authentication_required (the bank asked the cardholder to confirm it: buy the pack in Billing, then turn auto top-up back on), no_card (no saved card), billing_address_required (Stripe Tax needs the card's billing address: add it in the payment settings), payment_failed (another payment error), disputed (a payment on this account was disputed: auto top-up turns on again only with a different card), bank_inquiry (a bank asked about a payment on this account, which is not yet a dispute: turn it back on when you are ready), plan_ended (it bought a monthly plan's top-up, and the plan ended). It never retries: fix the cause, then turn it on again.",
                          "enum": [
                            "card_declined",
                            "authentication_required",
                            "no_card",
                            "billing_address_required",
                            "payment_failed",
                            "disputed",
                            "bank_inquiry",
                            "plan_ended"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "pack": {
                          "description": "The credit pack each top-up buys (catalog pack ID); null until auto top-up is first set up.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "payment_method": {
                          "description": "The saved card a top-up charges (the default card in the payment settings, else the newest); null when there is none, or when the payment processor could not be reached.",
                          "properties": {
                            "brand": {
                              "description": "Card brand (visa, mastercard, amex, …).",
                              "type": "string"
                            },
                            "exp_month": {
                              "description": "Expiry month (1–12).",
                              "type": "integer"
                            },
                            "exp_year": {
                              "description": "Expiry year.",
                              "type": "integer"
                            },
                            "last4": {
                              "description": "The card number's last four digits.",
                              "type": "string"
                            }
                          },
                          "required": [
                            "brand",
                            "last4",
                            "exp_month",
                            "exp_year"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "rolling_limit_cents": {
                          "description": "The most auto top-up charges in any 7 days, tax included, in cents, whatever monthly_cap_cents says: it grows with the payments that settled on this account, and support can lift it. A top-up that would pass it does not run (the owner is emailed); buying a pack by hand is never limited by it.",
                          "type": "integer"
                        },
                        "rolling_spent_cents": {
                          "description": "What auto top-up charged in the last 7 days, tax included, counting a charge in progress, in cents.",
                          "type": "integer"
                        },
                        "spent_this_month_cents": {
                          "description": "What auto top-up charged this calendar month, tax included, counting a charge in progress, in cents.",
                          "type": "integer"
                        },
                        "threshold": {
                          "description": "Credits: a balance change that leaves the balance at or below this buys the pack, once until the balance is above it again. null until set up.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "object",
                        "enabled",
                        "pack",
                        "threshold",
                        "monthly_cap_cents",
                        "currency",
                        "spent_this_month_cents",
                        "rolling_limit_cents",
                        "rolling_spent_cents",
                        "month_resets_at",
                        "off_reason",
                        "off_message",
                        "off_at",
                        "payment_method",
                        "last_charge",
                        "notice"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Turn auto top-up on or off, or change it",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Turn auto top-up on or off, or change it",
        "tags": [
          "Billing"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_error"
          ]
        }
      }
    },
    "/v1/billing/checkout": {
      "post": {
        "description": "Creates a Stripe Checkout session for a credit pack; open the returned url to pay. Credits are added when payment completes; GET /v1/billing/checkout/{id} follows it.",
        "operationId": "billing.checkout.create",
        "parameters": [
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "pack": {
                    "description": "Pack ID.",
                    "enum": [
                      "1k",
                      "30k",
                      "250k",
                      "2m",
                      "starter_topup",
                      "growth_topup",
                      "scale_topup"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "pack"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "Checkout session"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Buy a credit pack (Stripe Checkout)",
        "tags": [
          "Billing"
        ],
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/billing/checkout/{id}": {
      "get": {
        "description": "A purchase POST /v1/billing/checkout or POST /v1/billing/subscription/checkout started for this account, as Stripe has it, and whether its credits were added (a paid one's are, once, by the time it answers). Poll while open. Other accounts' sessions are not_found. Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "billing.checkout.get",
        "parameters": [
          {
            "description": "Checkout session ID (cs_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "amount_total": {
                          "description": "Paid, tax included, in the currency's smallest unit; null until known.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "credits": {
                          "description": "Credits the pack adds, or the plan adds each month.",
                          "type": "integer"
                        },
                        "credits_added": {
                          "description": "Whether its credits were added (once). A later refund or dispute takes back what is unspent.",
                          "type": "boolean"
                        },
                        "currency": {
                          "description": "amount_total's currency (ISO 4217); null until known.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "Checkout session ID (cs_…).",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always checkout_session.",
                          "enum": [
                            "checkout_session"
                          ],
                          "type": "string"
                        },
                        "pack": {
                          "description": "The credit pack bought (catalog pack ID); empty for a monthly plan.",
                          "type": "string"
                        },
                        "payment_status": {
                          "description": "paid once captured; a complete session stays unpaid while a delayed payment clears.",
                          "enum": [
                            "paid",
                            "unpaid",
                            "no_payment_required"
                          ],
                          "type": "string"
                        },
                        "plan": {
                          "description": "The monthly plan subscribed to (catalog plan ID); null for a credit pack.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "description": "open (not paid yet), complete (checkout finished) or expired (abandoned, nothing charged).",
                          "enum": [
                            "open",
                            "complete",
                            "expired"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "pack",
                        "plan",
                        "credits",
                        "status",
                        "payment_status",
                        "credits_added",
                        "amount_total",
                        "currency"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get a credit pack purchase",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Get a credit pack purchase",
        "tags": [
          "Billing"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_error"
          ]
        }
      }
    },
    "/v1/billing/portal": {
      "post": {
        "description": "A Stripe customer portal link for the account's payment settings: add, replace or remove the saved card that monthly plans and auto top-up charge, change the billing address and tax ID that sales tax and receipts use, and read past invoices. The dashboard session only, with a fresh sign-in: it shows the billing details and changes the card. Free.\n\n**Auth:** the dashboard session cookie.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "billing.portal.create",
        "parameters": [
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "object": {
                          "description": "Always billing_portal_session.",
                          "enum": [
                            "billing_portal_session"
                          ],
                          "type": "string"
                        },
                        "url": {
                          "description": "Open it to add, replace or remove the saved card and to change the billing address and tax ID. It works once, for a few minutes, and returns to the dashboard's billing page.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "url"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Open the payment settings (Stripe)",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Open the payment settings (Stripe)",
        "tags": [
          "Billing"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress",
            "upstream_error"
          ]
        }
      }
    },
    "/v1/billing/promo_codes/redeem": {
      "post": {
        "description": "Adds a promo code's credits to the account's balance, as a promo transaction in its credit history. They never expire. Each code works once per account, and once per email address of the account's owner, whatever account it is on. A code that can't be redeemed is answered invalid_input with param code and details.reason: unknown (no such code), expired (past its end, or withdrawn), used_up (redeemed as many times as it allows), already_redeemed (by this account, or by its owner's address on another) or not_eligible (an account whose owner's address is a throwaway one). The dashboard session only. Free.\n\n**Auth:** the dashboard session cookie.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "billing.promo_codes.redeem",
        "parameters": [
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "code": {
                    "description": "The promo code, as written anywhere: case, spaces around it and a leading # don't matter.",
                    "maxLength": 64,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "required": [
                  "code"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "balance": {
                          "description": "The account's balance with them.",
                          "type": "integer"
                        },
                        "code": {
                          "description": "The code redeemed, in capitals.",
                          "type": "string"
                        },
                        "credits": {
                          "description": "Credits it added. They never expire, like a pack's.",
                          "type": "integer"
                        },
                        "object": {
                          "description": "Always promo_redemption.",
                          "enum": [
                            "promo_redemption"
                          ],
                          "type": "string"
                        },
                        "redeemed_at": {
                          "description": "When it was redeemed, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "code",
                        "credits",
                        "balance",
                        "redeemed_at"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Redeem a promo code",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Redeem a promo code",
        "tags": [
          "Billing"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/billing/purchases": {
      "get": {
        "description": "Every payment the account made, newest first, cursor-paged: credit packs bought at checkout, auto top-ups, and monthly plan invoices (first months, renewals, upgrades), each with what it cost, its credits, and whether it was refunded or disputed. Its receipt is GET /v1/billing/purchases/{id}/receipt. Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "billing.purchases.list",
        "parameters": [
          {
            "description": "Purchases per page (default 25, at most 100).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "amount_refunded": {
                            "description": "Refunded so far, in currency's smallest unit; 0 when nothing was.",
                            "type": "integer"
                          },
                          "amount_total": {
                            "description": "Charged, tax included, in currency's smallest unit; null when not recorded.",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "created_at": {
                            "description": "When it was recorded, RFC 3339 UTC.",
                            "format": "date-time",
                            "type": "string"
                          },
                          "credits": {
                            "description": "Credits it adds: the pack's, or the plan's for the month.",
                            "type": "integer"
                          },
                          "currency": {
                            "description": "amount_total's currency (ISO 4217, lowercase); null when not recorded.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "id": {
                            "description": "Purchase ID: the Checkout session (cs_…) of a pack, the auto top-up (atu_…), or the plan's invoice (in_…).",
                            "type": "string"
                          },
                          "object": {
                            "description": "Always purchase.",
                            "enum": [
                              "purchase"
                            ],
                            "type": "string"
                          },
                          "pack": {
                            "description": "The credit pack bought (catalog pack ID); null for a plan, or when it is not recorded.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "plan": {
                            "description": "The monthly plan paid for (catalog plan ID); null for a pack, or when it is not recorded.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "description": "pending (a delayed payment, such as a bank debit, is clearing: its credits are added when it does), paid, failed (the delayed payment failed: nothing was charged or added), partially_refunded, refunded, or disputed (the cardholder's bank disputed it; a dispute closed in SocialTap's favor reads paid again).",
                            "enum": [
                              "pending",
                              "paid",
                              "failed",
                              "partially_refunded",
                              "refunded",
                              "disputed"
                            ],
                            "type": "string"
                          },
                          "type": {
                            "description": "pack (a credit pack bought at checkout), auto_top_up (a pack auto top-up bought with the saved card) or plan (a monthly plan's invoice: its first month, a renewal or an upgrade).",
                            "enum": [
                              "pack",
                              "auto_top_up",
                              "plan"
                            ],
                            "type": "string"
                          }
                        },
                        "required": [
                          "object",
                          "id",
                          "type",
                          "pack",
                          "plan",
                          "credits",
                          "status",
                          "amount_total",
                          "amount_refunded",
                          "currency",
                          "created_at"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List purchases",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "List purchases",
        "tags": [
          "Billing"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/billing/purchases/{id}/receipt": {
      "get": {
        "description": "A fresh link to a purchase's receipt, from Stripe: a monthly plan's invoice page (with its PDF), or a pack's or auto top-up's receipt (tax and refunds included). A pending purchase has none until its payment clears, and other accounts' purchases are not_found. Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "billing.purchases.receipt",
        "parameters": [
          {
            "description": "Purchase ID (cs_…, atu_… or in_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "id": {
                          "description": "The purchase ID.",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always purchase_receipt.",
                          "enum": [
                            "purchase_receipt"
                          ],
                          "type": "string"
                        },
                        "url": {
                          "description": "Stripe's page for it: a plan's invoice (with its PDF and its receipt), or a pack's receipt, which shows the tax and any refund and can be downloaded. Ask again for a fresh link rather than storing it.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "url"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get a purchase's receipt",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Get a purchase's receipt",
        "tags": [
          "Billing"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_error"
          ]
        }
      }
    },
    "/v1/billing/subscription": {
      "get": {
        "description": "The account's monthly plan: the plan paid for now, when it renews, what it changes to at renewal, and how much of the balance is monthly credits (spent first, ended at renewal). Without a plan, status is none and the account is pay as you go. Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "billing.subscription.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "cancel_at_period_end": {
                          "description": "Whether it ends at current_period_end instead of renewing. Monthly credits end with it; pack and top-up credits stay.",
                          "type": "boolean"
                        },
                        "current_period_end": {
                          "description": "When this month's credits end and the plan renews, or ends: RFC 3339 UTC; null without a monthly plan.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "Subscription ID (sub_…); null without a monthly plan.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "monthly_credits": {
                          "description": "Credits the plan adds at each renewal; 0 without a monthly plan.",
                          "type": "integer"
                        },
                        "monthly_credits_remaining": {
                          "description": "How much of the balance is monthly credits: requests spend these first, and what is left of them ends at the next renewal. The rest of the balance never expires.",
                          "type": "integer"
                        },
                        "next_plan": {
                          "description": "The plan it changes to at the next renewal, after a downgrade; null when it stays on plan.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "notice": {
                          "description": "What a person should know about the plan change just made, in a sentence to show them: its renewal is also being charged, say, or auto top-up's monthly cap is now below the top-up's price. Null otherwise, and on every read.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "object": {
                          "description": "Always subscription.",
                          "enum": [
                            "subscription"
                          ],
                          "type": "string"
                        },
                        "payment_url": {
                          "description": "Set when a plan change could not be paid yet (the card was declined, or the bank asks the cardholder to confirm): pay here within a day and the change applies. Null otherwise.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "plan": {
                          "description": "The plan paid for now (catalog plan ID); payg without a monthly plan.",
                          "type": "string"
                        },
                        "status": {
                          "description": "none (pay as you go), incomplete (the first payment is not through yet), active, past_due (the last renewal failed: Stripe retries it, and no new credits arrive until it is paid) or unpaid (the retries ended without payment).",
                          "enum": [
                            "none",
                            "incomplete",
                            "active",
                            "past_due",
                            "unpaid"
                          ],
                          "type": "string"
                        },
                        "top_up_pack": {
                          "description": "The credit pack this plan's subscribers can top up with when they run out (catalog pack ID, also for auto top-up); null without a monthly plan.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "plan",
                        "status",
                        "next_plan",
                        "cancel_at_period_end",
                        "current_period_end",
                        "monthly_credits",
                        "monthly_credits_remaining",
                        "top_up_pack",
                        "payment_url",
                        "notice"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get the monthly plan",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Get the monthly plan",
        "tags": [
          "Billing"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "patch": {
        "description": "Upgrades or downgrades the account's monthly plan. An upgrade starts now: the new plan's full price is charged to the saved card, a new month starts today, the plan's credits are added and the monthly credits left stay until the next renewal. A downgrade starts at the next renewal, with nothing charged now. It works in every state of the plan, and answers what the person should know in `notice`, or where to pay in `payment_url`; only an account with no card is refused, until it adds one. The dashboard session only, with no fresh sign-in: changing plan has to be as easy as subscribing was. Free.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "billing.subscription.update",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "plan": {
                    "description": "Change to this monthly plan (catalog plans). A dearer one starts now: its full price is charged to the saved card, a new month starts today, and the monthly credits left stay until the next renewal. A cheaper one starts at the next renewal, with nothing charged now.",
                    "maxLength": 20,
                    "type": "string"
                  }
                },
                "required": [
                  "plan"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "cancel_at_period_end": {
                          "description": "Whether it ends at current_period_end instead of renewing. Monthly credits end with it; pack and top-up credits stay.",
                          "type": "boolean"
                        },
                        "current_period_end": {
                          "description": "When this month's credits end and the plan renews, or ends: RFC 3339 UTC; null without a monthly plan.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "Subscription ID (sub_…); null without a monthly plan.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "monthly_credits": {
                          "description": "Credits the plan adds at each renewal; 0 without a monthly plan.",
                          "type": "integer"
                        },
                        "monthly_credits_remaining": {
                          "description": "How much of the balance is monthly credits: requests spend these first, and what is left of them ends at the next renewal. The rest of the balance never expires.",
                          "type": "integer"
                        },
                        "next_plan": {
                          "description": "The plan it changes to at the next renewal, after a downgrade; null when it stays on plan.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "notice": {
                          "description": "What a person should know about the plan change just made, in a sentence to show them: its renewal is also being charged, say, or auto top-up's monthly cap is now below the top-up's price. Null otherwise, and on every read.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "object": {
                          "description": "Always subscription.",
                          "enum": [
                            "subscription"
                          ],
                          "type": "string"
                        },
                        "payment_url": {
                          "description": "Set when a plan change could not be paid yet (the card was declined, or the bank asks the cardholder to confirm): pay here within a day and the change applies. Null otherwise.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "plan": {
                          "description": "The plan paid for now (catalog plan ID); payg without a monthly plan.",
                          "type": "string"
                        },
                        "status": {
                          "description": "none (pay as you go), incomplete (the first payment is not through yet), active, past_due (the last renewal failed: Stripe retries it, and no new credits arrive until it is paid) or unpaid (the retries ended without payment).",
                          "enum": [
                            "none",
                            "incomplete",
                            "active",
                            "past_due",
                            "unpaid"
                          ],
                          "type": "string"
                        },
                        "top_up_pack": {
                          "description": "The credit pack this plan's subscribers can top up with when they run out (catalog pack ID, also for auto top-up); null without a monthly plan.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "plan",
                        "status",
                        "next_plan",
                        "cancel_at_period_end",
                        "current_period_end",
                        "monthly_credits",
                        "monthly_credits_remaining",
                        "top_up_pack",
                        "payment_url",
                        "notice"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Change the monthly plan",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Change the monthly plan",
        "tags": [
          "Billing"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_error"
          ]
        }
      }
    },
    "/v1/billing/subscription/cancel": {
      "post": {
        "description": "Ends the account's monthly plan at the end of the month it is paid for, with no more charges and no refund for that month; monthly credits last until then, and pack and top-up credits stay. Until then, it can be undone. The dashboard session only, with no fresh sign-in: canceling only stops charges. Free.\n\n**Auth:** the dashboard session cookie.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "billing.subscription.cancel",
        "parameters": [
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "cancel_at_period_end": {
                    "description": "true ends the plan at current_period_end, with no more charges; monthly credits last until then. false keeps it renewing.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "cancel_at_period_end"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "cancel_at_period_end": {
                          "description": "Whether it ends at current_period_end instead of renewing. Monthly credits end with it; pack and top-up credits stay.",
                          "type": "boolean"
                        },
                        "current_period_end": {
                          "description": "When this month's credits end and the plan renews, or ends: RFC 3339 UTC; null without a monthly plan.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "Subscription ID (sub_…); null without a monthly plan.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "monthly_credits": {
                          "description": "Credits the plan adds at each renewal; 0 without a monthly plan.",
                          "type": "integer"
                        },
                        "monthly_credits_remaining": {
                          "description": "How much of the balance is monthly credits: requests spend these first, and what is left of them ends at the next renewal. The rest of the balance never expires.",
                          "type": "integer"
                        },
                        "next_plan": {
                          "description": "The plan it changes to at the next renewal, after a downgrade; null when it stays on plan.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "notice": {
                          "description": "What a person should know about the plan change just made, in a sentence to show them: its renewal is also being charged, say, or auto top-up's monthly cap is now below the top-up's price. Null otherwise, and on every read.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "object": {
                          "description": "Always subscription.",
                          "enum": [
                            "subscription"
                          ],
                          "type": "string"
                        },
                        "payment_url": {
                          "description": "Set when a plan change could not be paid yet (the card was declined, or the bank asks the cardholder to confirm): pay here within a day and the change applies. Null otherwise.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "plan": {
                          "description": "The plan paid for now (catalog plan ID); payg without a monthly plan.",
                          "type": "string"
                        },
                        "status": {
                          "description": "none (pay as you go), incomplete (the first payment is not through yet), active, past_due (the last renewal failed: Stripe retries it, and no new credits arrive until it is paid) or unpaid (the retries ended without payment).",
                          "enum": [
                            "none",
                            "incomplete",
                            "active",
                            "past_due",
                            "unpaid"
                          ],
                          "type": "string"
                        },
                        "top_up_pack": {
                          "description": "The credit pack this plan's subscribers can top up with when they run out (catalog pack ID, also for auto top-up); null without a monthly plan.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "plan",
                        "status",
                        "next_plan",
                        "cancel_at_period_end",
                        "current_period_end",
                        "monthly_credits",
                        "monthly_credits_remaining",
                        "top_up_pack",
                        "payment_url",
                        "notice"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Cancel the monthly plan, or undo it",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Cancel the monthly plan, or undo it",
        "tags": [
          "Billing"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress",
            "upstream_error"
          ]
        }
      }
    },
    "/v1/billing/subscription/checkout": {
      "post": {
        "description": "Creates a Stripe Checkout session that starts a monthly plan; open the returned url to pay. The plan's credits are added when the first payment completes, and again at each renewal, when what was left of them ends. GET /v1/billing/checkout/{id} follows it. An account already on a plan changes it with PATCH /v1/billing/subscription instead. The dashboard session only: it starts recurring charges. Free.\n\n**Auth:** the dashboard session cookie.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "billing.subscription.checkout",
        "parameters": [
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "plan": {
                    "description": "A public monthly plan's ID (catalog plans).",
                    "maxLength": 20,
                    "type": "string"
                  }
                },
                "required": [
                  "plan"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "id": {
                          "description": "Checkout session ID (cs_…); GET /v1/billing/checkout/{id} follows it.",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always checkout_session.",
                          "enum": [
                            "checkout_session"
                          ],
                          "type": "string"
                        },
                        "url": {
                          "description": "Stripe Checkout's page: open it to pay.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "url"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Start a monthly plan (Stripe Checkout)",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Start a monthly plan (Stripe Checkout)",
        "tags": [
          "Billing"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress",
            "upstream_error"
          ]
        }
      }
    },
    "/v1/bluesky/comments": {
      "get": {
        "description": "Returns the replies to a public Bluesky post, nested ones included, from its link or at:// ID, by most liked, newest or oldest. Each reply has parent_id saying what it answers, its text with hashtags, mentions and full link URLs, publish time, languages, labels, images and video, link card, the post it quotes, exact like, reply, repost, quote and bookmark counts, and the author with their verified badge and DID.\n\nReturns `{data, page, meta}`: `data` holds up to 1000 `Comment` items (the shared schema, the same on every platform), Most liked first, the replies Bluesky folds under \"Show more replies\" last with sort=popular (the default), newest first with sort=newest, oldest first with sort=oldest. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/bluesky/comments/ (Markdown: https://socialtap.dev/docs/reference/bluesky/comments/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/bluesky/comments/index.md)",
          "url": "https://socialtap.dev/docs/reference/bluesky/comments/"
        },
        "operationId": "bluesky.comments.list",
        "parameters": [
          {
            "description": "The post: its link (bsky.app/profile/bsky.app/post/3l6oveex3ii2l), by the account's handle or DID, with any route under it (/liked-by, /reposted-by, /quotes), the embed page's link, or its at:// ID (at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l). A comment's id or link lists the replies to that comment.",
            "example": "https://bsky.app/profile/atproto.com/post/3moduzldxr22q",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The post: its link (bsky.app/profile/bsky.app/post/3l6oveex3ii2l), by the account's handle or DID, with any route under it (/liked-by, /reposted-by, /quotes), the embed page's link, or its at:// ID (at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l). A comment's id or link lists the replies to that comment.",
              "examples": [
                "https://bsky.app/profile/bsky.app/post/3l6oveex3ii2l"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. popular (default): the most liked replies first, the ones Bluesky folds under \"Show more replies\" last. newest: newest first. oldest: oldest first. Each orders the whole list, nested replies among the rest; parent_id says what each replies to.",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "popular",
              "description": "Order of the results. popular (default): the most liked replies first, the ones Bluesky folds under \"Show more replies\" last. newest: newest first. oldest: oldest first. Each orders the whole list, nested replies among the rest; parent_id says what each replies to.",
              "enum": [
                "popular",
                "newest",
                "oldest"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 1000,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 1000,
              "maximum": 1000,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:rnpkyqnmsw4ipey6eotbdnnf/bafkreierosmj3aqp63zskykqo7ucl6vs4adep5op27tzkr6zhoxdaqjvjy",
                            "display_name": "Bailey Townsend 🦀",
                            "id": "did:plc:rnpkyqnmsw4ipey6eotbdnnf",
                            "is_verified": true,
                            "url": "https://bsky.app/profile/pds.dad",
                            "username": "pds.dad"
                          },
                          "edited_at": null,
                          "id": "at://did:plc:rnpkyqnmsw4ipey6eotbdnnf/app.bsky.feed.post/3modvwakvu22v",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 11,
                            "reply_count": 0
                          },
                          "parent_id": null,
                          "platform": "bluesky",
                          "platform_specific": {
                            "bluesky": {
                              "bridged_from_url": null,
                              "cid": "bafyreiba2dzwa45xz6yxqu7wbzoz52ni2qshhkcihwsdzjuk2hjnsjfgse",
                              "created_at": "2026-06-15T18:26:52Z",
                              "embedded_record_uri": null,
                              "hashtags": [],
                              "indexed_at": "2026-06-15T18:26:53Z",
                              "is_hidden": false,
                              "is_hidden_by_post_author": false,
                              "is_nsfw": false,
                              "labels": [],
                              "languages": [
                                "en"
                              ],
                              "link_card": null,
                              "links": [],
                              "media": [],
                              "mentions": [],
                              "quote_count": 0,
                              "quoted_post": null,
                              "quoted_post_id": null,
                              "reply_root_post_id": "at://did:plc:ewvi7nxzyoun6zhxrhs64oiz/app.bsky.feed.post/3moduzldxr22q",
                              "repost_count": 0,
                              "save_count": 0
                            }
                          },
                          "post_id": "at://did:plc:ewvi7nxzyoun6zhxrhs64oiz/app.bsky.feed.post/3moduzldxr22q",
                          "published_at": "2026-06-15T18:26:52Z",
                          "text": "Not sure if it’s already be answered, but…\n\nWhat’s the migration story looking like? One export like a .car? Then to add on if it’s single export can the import process be looked at to be a bit nicer on memory for large imports (75mb+ ball park) 👀",
                          "unknown_fields": [],
                          "url": "https://bsky.app/profile/pds.dad/post/3modvwakvu22v"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:mmyj7mk7kh3jqhw6zs4prbuk/bafkreiebc6p2hzm26gis7zkxc6cnljx2nf5jj5bne6quy7hz4in2bcq4ju",
                            "display_name": "Meri",
                            "id": "did:plc:mmyj7mk7kh3jqhw6zs4prbuk",
                            "is_verified": false,
                            "url": "https://bsky.app/profile/meri.garden",
                            "username": "meri.garden"
                          },
                          "edited_at": null,
                          "id": "at://did:plc:mmyj7mk7kh3jqhw6zs4prbuk/app.bsky.feed.post/3moelxyfdqk2j",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 9,
                            "reply_count": 0
                          },
                          "parent_id": null,
                          "platform": "bluesky",
                          "platform_specific": {
                            "bluesky": {
                              "bridged_from_url": null,
                              "cid": "bafyreib7kgmwpcgv3szz73cdr5e4m6accssoqhhc2dmzt4fomifci3mpw4",
                              "created_at": "2026-06-16T01:01:32Z",
                              "embedded_record_uri": null,
                              "hashtags": [],
                              "indexed_at": "2026-06-16T01:01:34Z",
                              "is_hidden": false,
                              "is_hidden_by_post_author": false,
                              "is_nsfw": false,
                              "labels": [],
                              "languages": [
                                "en"
                              ],
                              "link_card": null,
                              "links": [],
                              "media": [],
                              "mentions": [],
                              "quote_count": 0,
                              "quoted_post": null,
                              "quoted_post_id": null,
                              "reply_root_post_id": "at://did:plc:ewvi7nxzyoun6zhxrhs64oiz/app.bsky.feed.post/3moduzldxr22q",
                              "repost_count": 2,
                              "save_count": 0
                            }
                          },
                          "post_id": "at://did:plc:ewvi7nxzyoun6zhxrhs64oiz/app.bsky.feed.post/3moduzldxr22q",
                          "published_at": "2026-06-16T01:01:32Z",
                          "text": "I'm wondering about Bluesky group chats - will these be migrated to permissioned spaces when they are ready? And will ownership of those spaces be transferrable (seperate DID)?",
                          "unknown_fields": [],
                          "url": "https://bsky.app/profile/meri.garden/post/3moelxyfdqk2j"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:wzjoqxvghocxiu6sn4xwtyfh/bafkreicbgmp5ojmrrpcenvqdcyq6i2df66sjhck6zos3g55yeuerf5ljaq",
                            "display_name": "woke oak",
                            "id": "did:plc:wzjoqxvghocxiu6sn4xwtyfh",
                            "is_verified": false,
                            "url": "https://bsky.app/profile/oakley.bsky.social",
                            "username": "oakley.bsky.social"
                          },
                          "edited_at": null,
                          "id": "at://did:plc:wzjoqxvghocxiu6sn4xwtyfh/app.bsky.feed.post/3modvdlxrtk23",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 4,
                            "reply_count": 0
                          },
                          "parent_id": null,
                          "platform": "bluesky",
                          "platform_specific": {
                            "bluesky": {
                              "bridged_from_url": null,
                              "cid": "bafyreif7xabmmlxz43bgd5v7id73qi7sqbgloqsueadrbo7uwgdd63uvzy",
                              "created_at": "2026-06-15T18:16:26Z",
                              "embedded_record_uri": null,
                              "hashtags": [],
                              "indexed_at": "2026-06-15T18:16:26Z",
                              "is_hidden": false,
                              "is_hidden_by_post_author": false,
                              "is_nsfw": false,
                              "labels": [],
                              "languages": [
                                "en"
                              ],
                              "link_card": null,
                              "links": [],
                              "media": [],
                              "mentions": [],
                              "quote_count": 0,
                              "quoted_post": null,
                              "quoted_post_id": null,
                              "reply_root_post_id": "at://did:plc:ewvi7nxzyoun6zhxrhs64oiz/app.bsky.feed.post/3moduzldxr22q",
                              "repost_count": 0,
                              "save_count": 0
                            }
                          },
                          "post_id": "at://did:plc:ewvi7nxzyoun6zhxrhs64oiz/app.bsky.feed.post/3moduzldxr22q",
                          "published_at": "2026-06-15T18:16:26Z",
                          "text": "what's the rollout gonna look like? bluesky was a private beta to test the protocol with a separate federation sandbox for months before either publicly launched, will anything similar here happen? \n\ncan i have an invite?",
                          "unknown_fields": [],
                          "url": "https://bsky.app/profile/oakley.bsky.social/post/3modvdlxrtk23"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "bluesky",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 329,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "at://did:plc:ewvi7nxzyoun6zhxrhs64oiz/app.bsky.feed.post/3moduzldxr22q",
                          "url": "https://bsky.app/profile/atproto.com/post/3moduzldxr22q"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "end"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/BlueskyCommentsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Replies to a post, nested ones included",
        "tags": [
          "Bluesky"
        ],
        "x-socialtap-endpoint": "bluesky.comments",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Most liked first, the replies Bluesky folds under \"Show more replies\" last",
          "orders": {
            "newest": "newest first",
            "oldest": "oldest first",
            "popular": "Most liked first, the replies Bluesky folds under \"Show more replies\" last"
          },
          "page_max": 1000,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/bluesky/post": {
      "get": {
        "description": "Returns a public Bluesky post from any of its links or its at:// ID, with exact like, reply, repost, quote and bookmark counts. It also has the full text with hashtags, mentions and full link URLs, the publish time, languages, images and video with alt text, the link card, the post it quotes, the post it replies to and the thread's root, moderation labels, and the author with their verified badge and stable DID.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/bluesky/post/ (Markdown: https://socialtap.dev/docs/reference/bluesky/post/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/bluesky/post/index.md)",
          "url": "https://socialtap.dev/docs/reference/bluesky/post/"
        },
        "operationId": "bluesky.post.get",
        "parameters": [
          {
            "description": "The post: its link (bsky.app/profile/bsky.app/post/3l6oveex3ii2l), by the account's handle or DID, with any route under it (/liked-by, /reposted-by, /quotes), the embed page's link, or its at:// ID (at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l), which is the id every answer gives. The short key at the end of a link names no post without its account.",
            "example": "https://bsky.app/profile/bsky.app/post/3l6oveex3ii2l",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The post: its link (bsky.app/profile/bsky.app/post/3l6oveex3ii2l), by the account's handle or DID, with any route under it (/liked-by, /reposted-by, /quotes), the embed page's link, or its at:// ID (at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l), which is the id every answer gives. The short key at the end of a link names no post without its account.",
              "examples": [
                "https://bsky.app/profile/bsky.app/post/3l6oveex3ii2l"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:z72i7hdynmk6r22z27h6tvur/bafkreihwihm6kpd6zuwhhlro75p5qks5qtrcu55jp3gddbfjsieiv7wuka",
                          "display_name": "Bluesky",
                          "id": "did:plc:z72i7hdynmk6r22z27h6tvur",
                          "is_verified": true,
                          "url": "https://bsky.app/profile/bsky.app",
                          "username": "bsky.app"
                        },
                        "coauthors": [],
                        "duration_ms": null,
                        "hashtags": [],
                        "id": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l",
                        "is_nsfw": false,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": "en",
                        "media": [],
                        "mentions": [],
                        "metrics": {
                          "comment_count": 8711,
                          "like_count": 63751,
                          "quote_count": 723,
                          "repost_count": 9550,
                          "save_count": 276,
                          "share_count": null,
                          "view_count": null
                        },
                        "platform": "bluesky",
                        "platform_specific": {
                          "bluesky": {
                            "bridged_from_url": null,
                            "cid": "bafyreicnt42y6vo6pfpvyro234ac4o6ijug6adwwrh7awflgrqlt4zibxq",
                            "created_at": "2024-10-17T07:06:51Z",
                            "embedded_record_uri": null,
                            "indexed_at": "2024-10-17T07:06:51Z",
                            "labels": [],
                            "languages": [
                              "en"
                            ],
                            "link_card": null,
                            "links": [],
                            "quoted_post": null,
                            "quoted_post_id": null,
                            "reply_root_post_id": null,
                            "reply_to_post_id": null,
                            "reposted_at": null,
                            "reposted_by": null
                          }
                        },
                        "platform_type": null,
                        "published_at": "2024-10-17T07:06:51Z",
                        "text": "👋  Bluesky is an open social network that gives creators independence from platforms, developers the freedom to build, and users a choice in their experience. We're so excited to have you here! \n\nWe share Bluesky updates & news from this account. A quick orientation thread: 🧵✨",
                        "thumbnail_url": null,
                        "title": null,
                        "type": "text",
                        "unknown_fields": [],
                        "url": "https://bsky.app/profile/bsky.app/post/3l6oveex3ii2l"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "bluesky",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 206,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l",
                          "url": "https://bsky.app/profile/bsky.app/post/3l6oveex3ii2l"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/BlueskyPostResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact likes, replies, reposts and quotes",
        "tags": [
          "Bluesky"
        ],
        "x-socialtap-endpoint": "bluesky.post",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/bluesky/posts": {
      "get": {
        "description": "Returns a public Bluesky account's posts and reposts from its handle, DID or profile link, as the tabs of its profile list them. Ask for its replies too, or only posts with media or video. Each post has its link, publish time, full text with hashtags, mentions and full link URLs, images and video, link card, quote and reply, the pin, and exact like, reply, repost, quote and bookmark counts. A repost also says who reposted it and when.\n\nReturns `{data, page, meta}`: `data` holds up to 100 `Post` items (the shared schema, the same on every platform), most recent activity first: a post by when it was posted, a repost by when it was reposted. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/bluesky/posts/ (Markdown: https://socialtap.dev/docs/reference/bluesky/posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/bluesky/posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/bluesky/posts/"
        },
        "operationId": "bluesky.posts.list",
        "parameters": [
          {
            "description": "The Bluesky account: its handle, with or without the @ (alice.bsky.social, espn.com), its DID (did:plc:z72i7hdynmk6r22z27h6tvur, did:web:didweb.watch), which is the id every answer gives, or a link to its profile.",
            "example": "espn.com",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Bluesky account: its handle, with or without the @ (alice.bsky.social, espn.com), its DID (did:plc:z72i7hdynmk6r22z27h6tvur, did:web:didweb.watch), which is the id every answer gives, or a link to its profile.",
              "examples": [
                "espn.com"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Which of the profile's tabs to list: posts (default): its posts, its own threads and its reposts, without its replies to others; replies: those too; media: its posts with images or video; video: its posts with a video.",
            "example": "replies",
            "in": "query",
            "name": "tab",
            "schema": {
              "description": "Which of the profile's tabs to list: posts (default): its posts, its own threads and its reposts, without its replies to others; replies: those too; media: its posts with images or video; video: its posts with a video.",
              "enum": [
                "posts",
                "replies",
                "media",
                "video"
              ],
              "examples": [
                "replies"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at, so a recent repost of an older post is left out. The walk stops once the list is older than this.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at, so a recent repost of an older post is left out. The walk stops once the list is older than this.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). The list starts at this time, so a later repost isn't listed, even of an older post, and is_pinned is null.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). The list starts at this time, so a later repost isn't listed, even of an older post, and is_pinned is null.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 100,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:x7d6j54pm22ufehkes6jo4jf/bafkreie4oxawqqsfzvk47ysr3unsnmviedzpylxmwxnpa534to2bzas4ie",
                            "display_name": "ESPN",
                            "id": "did:plc:x7d6j54pm22ufehkes6jo4jf",
                            "is_verified": true,
                            "url": "https://bsky.app/profile/espn.com",
                            "username": "espn.com"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "at://did:plc:x7d6j54pm22ufehkes6jo4jf/app.bsky.feed.post/3muznlkmspz2x",
                          "is_nsfw": false,
                          "is_pinned": false,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://video.bsky.app/watch/did%3Aplc%3Ax7d6j54pm22ufehkes6jo4jf/bafkreiflqivgi6afl5jv4qnmwzo3ks7jwe2dfurohsjfgafbtd5crw4gaq/thumbnail.jpg",
                              "type": "video",
                              "url": "https://video.bsky.app/watch/did%3Aplc%3Ax7d6j54pm22ufehkes6jo4jf/bafkreiflqivgi6afl5jv4qnmwzo3ks7jwe2dfurohsjfgafbtd5crw4gaq/playlist.m3u8",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 15,
                            "like_count": 103,
                            "quote_count": 7,
                            "repost_count": 11,
                            "save_count": 0,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "bluesky",
                          "platform_specific": {
                            "bluesky": {
                              "bridged_from_url": null,
                              "cid": "bafyreiceaay7jrgqznvxhttsmizofewx3mj6bwebjtz76nd2wh4hix4fty",
                              "created_at": "2026-09-08T18:27:24Z",
                              "embedded_record_uri": null,
                              "indexed_at": "2026-09-08T18:27:30Z",
                              "labels": [],
                              "languages": [],
                              "link_card": null,
                              "links": [],
                              "quoted_post": null,
                              "quoted_post_id": null,
                              "reply_root_post_id": null,
                              "reply_to_post_id": null,
                              "reposted_at": null,
                              "reposted_by": null
                            }
                          },
                          "platform_type": null,
                          "published_at": "2026-09-08T18:27:24Z",
                          "text": "One more sleep until NFL football is BACK. 🏈",
                          "thumbnail_url": "https://video.bsky.app/watch/did%3Aplc%3Ax7d6j54pm22ufehkes6jo4jf/bafkreiflqivgi6afl5jv4qnmwzo3ks7jwe2dfurohsjfgafbtd5crw4gaq/thumbnail.jpg",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://bsky.app/profile/espn.com/post/3muznlkmspz2x"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:x7d6j54pm22ufehkes6jo4jf/bafkreie4oxawqqsfzvk47ysr3unsnmviedzpylxmwxnpa534to2bzas4ie",
                            "display_name": "ESPN",
                            "id": "did:plc:x7d6j54pm22ufehkes6jo4jf",
                            "is_verified": true,
                            "url": "https://bsky.app/profile/espn.com",
                            "username": "espn.com"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "at://did:plc:x7d6j54pm22ufehkes6jo4jf/app.bsky.feed.post/3mpglmolczz2w",
                          "is_nsfw": false,
                          "is_pinned": false,
                          "is_sponsored": null,
                          "language": null,
                          "media": [],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 17,
                            "like_count": 139,
                            "quote_count": 16,
                            "repost_count": 34,
                            "save_count": 1,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "bluesky",
                          "platform_specific": {
                            "bluesky": {
                              "bridged_from_url": null,
                              "cid": "bafyreid2eoctnshw7unb5ozrjqsy63kpqmwwvhj2xuxsfo4z5zucfazqum",
                              "created_at": "2026-06-29T13:25:44Z",
                              "embedded_record_uri": null,
                              "indexed_at": "2026-06-29T13:25:45Z",
                              "labels": [],
                              "languages": [],
                              "link_card": {
                                "description": "Former Titans and Cardinals running back Chris Johnson told \"Good Morning America\" that he was diagnosed with ALS in 2025.",
                                "thumbnail_url": "https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:x7d6j54pm22ufehkes6jo4jf/bafkreicgzhnme4wgvolagtic3dki5icwfkmlxz23cmakg2mj2h4xkwvg2q",
                                "title": "Former NFL RB Chris Johnson discusses ALS diagnosis",
                                "url": "http://spr.ly/63329BDvG6W"
                              },
                              "links": [],
                              "quoted_post": null,
                              "quoted_post_id": null,
                              "reply_root_post_id": null,
                              "reply_to_post_id": null,
                              "reposted_at": null,
                              "reposted_by": null
                            }
                          },
                          "platform_type": null,
                          "published_at": "2026-06-29T13:25:44Z",
                          "text": "Former Tennessee Titans and Arizona Cardinals running back Chris Johnson revealed that he has been diagnosed with ALS in an interview with ABC's \"Good Morning America\".\n\nJohnson, 39, told GMA co-anchor Michael Strahan that he was diagnosed with the disease in 2025.",
                          "thumbnail_url": "https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:x7d6j54pm22ufehkes6jo4jf/bafkreicgzhnme4wgvolagtic3dki5icwfkmlxz23cmakg2mj2h4xkwvg2q",
                          "title": null,
                          "type": "link",
                          "unknown_fields": [],
                          "url": "https://bsky.app/profile/espn.com/post/3mpglmolczz2w"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "bluesky",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 449,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "did:plc:x7d6j54pm22ufehkes6jo4jf",
                          "url": "https://bsky.app/profile/espn.com"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/BlueskyPostsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Posts and reposts with exact counts",
        "tags": [
          "Bluesky"
        ],
        "x-socialtap-endpoint": "bluesky.posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "most recent activity first: a post by when it was posted, a repost by when it was reposted",
          "page_max": 100,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/bluesky/profile": {
      "get": {
        "description": "Returns a public Bluesky profile from its handle, DID or link, with exact follower, following and post counts. It also has the stable DID and current handle, display name, bio, pronouns, avatar, banner, join date, the verified badge with who verified the account and when, its links with their titles, labels such as bot, its pinned post, and how many lists, custom feeds and starter packs it made.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/bluesky/profile/ (Markdown: https://socialtap.dev/docs/reference/bluesky/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/bluesky/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/bluesky/profile/"
        },
        "operationId": "bluesky.profile.get",
        "parameters": [
          {
            "description": "The Bluesky account: its handle, a domain name (espn.com, alice.bsky.social), with or without the @; its DID (did:plc:z72i7hdynmk6r22z27h6tvur or did:web:…), which is the id every answer gives and survives a change of handle; or its link (https://bsky.app/profile/bsky.app), by handle or DID, with any tab under it. A word without a dot is no handle: Bluesky's own are written in full, as alice.bsky.social.",
            "example": "espn.com",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Bluesky account: its handle, a domain name (espn.com, alice.bsky.social), with or without the @; its DID (did:plc:z72i7hdynmk6r22z27h6tvur or did:web:…), which is the id every answer gives and survives a change of handle; or its link (https://bsky.app/profile/bsky.app), by handle or DID, with any tab under it. A word without a dot is no handle: Bluesky's own are written in full, as alice.bsky.social.",
              "examples": [
                "bsky.app"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:x7d6j54pm22ufehkes6jo4jf/bafkreie4oxawqqsfzvk47ysr3unsnmviedzpylxmwxnpa534to2bzas4ie",
                        "banner_url": null,
                        "bio": "Serving sports fans. Anytime. Anywhere.",
                        "category": null,
                        "country_code": null,
                        "created_at": "2024-11-25T21:49:49Z",
                        "display_name": "ESPN",
                        "external_links": [],
                        "id": "did:plc:x7d6j54pm22ufehkes6jo4jf",
                        "is_private": false,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 305103,
                          "following_count": 32,
                          "post_count": 872,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "bluesky",
                        "platform_specific": {
                          "bluesky": {
                            "feed_count": 0,
                            "indexed_at": "2024-12-19T20:49:48Z",
                            "is_labeler": false,
                            "is_trusted_verifier": false,
                            "labels": [],
                            "list_count": 0,
                            "pinned_post_id": null,
                            "pronouns": null,
                            "starter_pack_count": 0,
                            "verified_by": [
                              {
                                "created_at": "2025-04-21T10:44:20Z",
                                "id": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.graph.verification/3lndppjqgb72f",
                                "is_valid": true,
                                "issuer": {
                                  "avatar_url": null,
                                  "display_name": "Bluesky",
                                  "id": "did:plc:z72i7hdynmk6r22z27h6tvur",
                                  "is_verified": null,
                                  "url": "https://bsky.app/profile/bsky.app",
                                  "username": "bsky.app"
                                }
                              }
                            ]
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://bsky.app/profile/espn.com",
                        "username": "espn.com"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "bluesky",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 196,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "did:plc:x7d6j54pm22ufehkes6jo4jf",
                          "url": "https://bsky.app/profile/espn.com"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/BlueskyProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact follower counts, bio, links and DID",
        "tags": [
          "Bluesky"
        ],
        "x-socialtap-endpoint": "bluesky.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/bluesky/search_posts": {
      "get": {
        "description": "Returns public Bluesky posts that match your words, newest or top first, filtered by date, language, author, mention, hashtag or site. Each post has its link, publish time, full text with hashtags, mentions and full link URLs, images and video, link card, quote and reply, and exact like, reply, repost, quote and bookmark counts. Page back through the newest-first results with the cursor.\n\nReturns `{data, page, meta}`: `data` holds up to 100 `Post` items (the shared schema, the same on every platform), newest first, by the time each post states, to the second with sort=newest (the default), Bluesky's Top ranking with sort=popular. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/bluesky/search_posts/ (Markdown: https://socialtap.dev/docs/reference/bluesky/search_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/bluesky/search_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/bluesky/search_posts/"
        },
        "operationId": "bluesky.search_posts.list",
        "parameters": [
          {
            "description": "Words to find posts by, as Bluesky's search reads them: a topic, a phrase in quotes, a #hashtag or an @handle, and a leading - leaves a word out (climate change, \"coffee roaster\" -bean, #atproto). Bluesky's own from:, to:, mentions:, since:, until:, lang: and domain: operators are read as this endpoint's params.",
            "example": "bitcoin",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find posts by, as Bluesky's search reads them: a topic, a phrase in quotes, a #hashtag or an @handle, and a leading - leaves a word out (climate change, \"coffee roaster\" -bean, #atproto). Bluesky's own from:, to:, mentions:, since:, until:, lang: and domain: operators are read as this endpoint's params.",
              "examples": [
                "climate change"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. newest (default): newest first, a page after a page back through time. popular: Bluesky's Top ranking, which favours posts with engagement, one page only.",
            "example": "newest",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "newest",
              "description": "Order of the results. newest (default): newest first, a page after a page back through time. popular: Bluesky's Top ranking, which favours posts with engagement, one page only.",
              "enum": [
                "newest",
                "popular"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only posts by this account: a handle, a DID or a profile link.",
            "example": "espn.com",
            "in": "query",
            "name": "author",
            "schema": {
              "description": "Only posts by this account: a handle, a DID or a profile link.",
              "examples": [
                "espn.com"
              ],
              "maxLength": 300,
              "type": "string"
            }
          },
          {
            "description": "Only posts that mention this account: a handle, a DID or a profile link.",
            "example": "nasa.gov",
            "in": "query",
            "name": "mentions",
            "schema": {
              "description": "Only posts that mention this account: a handle, a DID or a profile link.",
              "examples": [
                "nasa.gov"
              ],
              "maxLength": 300,
              "type": "string"
            }
          },
          {
            "description": "Only posts with this hashtag, with or without the #.",
            "example": "atproto",
            "in": "query",
            "name": "tag",
            "schema": {
              "description": "Only posts with this hashtag, with or without the #.",
              "examples": [
                "atproto"
              ],
              "maxLength": 100,
              "type": "string"
            }
          },
          {
            "description": "Only posts that link to this domain or a subdomain of it.",
            "example": "espn.com",
            "in": "query",
            "name": "domain",
            "schema": {
              "description": "Only posts that link to this domain or a subdomain of it.",
              "examples": [
                "espn.com"
              ],
              "maxLength": 253,
              "type": "string"
            }
          },
          {
            "description": "Only posts that link to this page: a full URL.",
            "example": "https://www.nytimes.com/",
            "in": "query",
            "name": "links_to",
            "schema": {
              "description": "Only posts that link to this page: a full URL.",
              "examples": [
                "https://www.nytimes.com/"
              ],
              "maxLength": 2000,
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). Only posts in this language, by the tags their author set: a BCP-47 tag, of which Bluesky reads the language alone (pt-BR finds what pt finds).",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). Only posts in this language, by the tags their author set: a BCP-47 tag, of which Bluesky reads the language alone (pt-BR finds what pt finds).",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. By the post's stated time, to the second.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. By the post's stated time, to the second.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). By the post's stated time, to the second.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). By the post's stated time, to the second.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 100,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:hlod3gl5ewwglnr4yarddcrk/bafkreihy5kd5vnqqs77wtxzdf5kdyq24x23vtawwb5knkz7wh5yesamsoy",
                            "display_name": "Swiss Whale Intelligence 🇨🇭",
                            "id": "did:plc:hlod3gl5ewwglnr4yarddcrk",
                            "is_verified": false,
                            "url": "https://bsky.app/profile/btcwhalealerts.com",
                            "username": "btcwhalealerts.com"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [
                            "Bitcoin",
                            "Crypto"
                          ],
                          "id": "at://did:plc:hlod3gl5ewwglnr4yarddcrk/app.bsky.feed.post/3mzjyfostuj2n",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 0,
                            "like_count": 0,
                            "quote_count": 0,
                            "repost_count": 0,
                            "save_count": 0,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "bluesky",
                          "platform_specific": {
                            "bluesky": {
                              "bridged_from_url": null,
                              "cid": "bafyreiduygaoktbbpfbii3ds5d4nkmu5c3yfjwqvlwkeqzrhoxa5gxpgvy",
                              "created_at": "2026-11-05T04:04:24Z",
                              "embedded_record_uri": null,
                              "indexed_at": "2026-11-05T04:04:24Z",
                              "labels": [],
                              "languages": [
                                "en"
                              ],
                              "link_card": null,
                              "links": [
                                "https://swisswhaleintelligence.com/tx/8b044d3165b582ac112c14b3afc7ff017dba8bd3f124b03dbbf9912a27e0bfaa"
                              ],
                              "quoted_post": null,
                              "quoted_post_id": null,
                              "reply_root_post_id": null,
                              "reply_to_post_id": null,
                              "reposted_at": null,
                              "reposted_by": null
                            }
                          },
                          "platform_type": null,
                          "published_at": "2026-11-05T04:04:24Z",
                          "text": "🐳 4,259 BTC ($343.7M) whale transfer\nPast similar activity: avg -2.2% price drop 72h after.\n\nhttps://swisswhaleintelligence.com/tx/8b044d3165b582ac112c14b3afc7ff017dba8bd3f124b03dbbf9912a27e0bfaa #Bitcoin #Crypto",
                          "thumbnail_url": null,
                          "title": null,
                          "type": "text",
                          "unknown_fields": [],
                          "url": "https://bsky.app/profile/btcwhalealerts.com/post/3mzjyfostuj2n"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:pnmlwvud7rkanzzns5nanon6/bafkreibjn6xzku5qrjmp4s7abkf753wh5h7youodu7jgynnwtnwtbl2ciu",
                            "display_name": "Pandavana Crypto News",
                            "id": "did:plc:pnmlwvud7rkanzzns5nanon6",
                            "is_verified": false,
                            "url": "https://bsky.app/profile/pandacrypto.bsky.social",
                            "username": "pandacrypto.bsky.social"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [
                            "Crypto",
                            "Solana"
                          ],
                          "id": "at://did:plc:pnmlwvud7rkanzzns5nanon6/app.bsky.feed.post/3mzjyf2labq2g",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 0,
                            "like_count": 0,
                            "quote_count": 0,
                            "repost_count": 0,
                            "save_count": 0,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "bluesky",
                          "platform_specific": {
                            "bluesky": {
                              "bridged_from_url": null,
                              "cid": "bafyreibohrvfnua3lpwuaqnnfssupil4q64mrmtzlktlqchfuqzrnubx3e",
                              "created_at": "2026-11-05T04:04:02Z",
                              "embedded_record_uri": null,
                              "indexed_at": "2026-11-05T04:04:03Z",
                              "labels": [],
                              "languages": [],
                              "link_card": null,
                              "links": [],
                              "quoted_post": null,
                              "quoted_post_id": null,
                              "reply_root_post_id": null,
                              "reply_to_post_id": null,
                              "reposted_at": null,
                              "reposted_by": null
                            }
                          },
                          "platform_type": null,
                          "published_at": "2026-11-05T04:04:02Z",
                          "text": "#Crypto Prices:\r\n\r\nBitcoin $80,414.50\r\nEthereum $2,418.80\r\nXRP $1.31\r\n#Solana $96.16\r\nSui $0.93\r\n\r\n\r\n",
                          "thumbnail_url": null,
                          "title": null,
                          "type": "text",
                          "unknown_fields": [],
                          "url": "https://bsky.app/profile/pandacrypto.bsky.social/post/3mzjyf2labq2g"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:vjpyc66fyniyqp2v6j7mxdvm/bafkreicg6htpnqv6cih6dhdxemkzugqmg4sqpgsfys5stz74ckwocynnoi",
                            "display_name": "miatone.bsky.social",
                            "id": "did:plc:vjpyc66fyniyqp2v6j7mxdvm",
                            "is_verified": false,
                            "url": "https://bsky.app/profile/miatone.bsky.social",
                            "username": "miatone.bsky.social"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "at://did:plc:vjpyc66fyniyqp2v6j7mxdvm/app.bsky.feed.post/3mzjya6ieog2l",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 0,
                            "like_count": 0,
                            "quote_count": 0,
                            "repost_count": 0,
                            "save_count": 0,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "bluesky",
                          "platform_specific": {
                            "bluesky": {
                              "bridged_from_url": null,
                              "cid": "bafyreib4vxlqmmhsycxfkhzj27k4466dgooh2rbmiod3gqf2bey3ryiqxu",
                              "created_at": "2026-11-05T04:01:18Z",
                              "embedded_record_uri": null,
                              "indexed_at": "2026-11-05T04:01:19Z",
                              "labels": [],
                              "languages": [],
                              "link_card": null,
                              "links": [],
                              "quoted_post": null,
                              "quoted_post_id": null,
                              "reply_root_post_id": null,
                              "reply_to_post_id": null,
                              "reposted_at": null,
                              "reposted_by": null
                            }
                          },
                          "platform_type": null,
                          "published_at": "2026-11-05T04:01:18Z",
                          "text": "This caught my attention today: Nearly $1 Billion in Crypto Liquidations Hit as Bitcoin Jumps 4.6%",
                          "thumbnail_url": null,
                          "title": null,
                          "type": "text",
                          "unknown_fields": [],
                          "url": "https://bsky.app/profile/miatone.bsky.social/post/3mzjya6ieog2l"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "bluesky",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 560,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/BlueskySearch_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Posts by keyword, hashtag, author or link",
        "tags": [
          "Bluesky"
        ],
        "x-socialtap-endpoint": "bluesky.search_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first, by the time each post states, to the second",
          "orders": {
            "newest": "newest first, by the time each post states, to the second",
            "popular": "Bluesky's Top ranking"
          },
          "page_max": 100,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/credit_transactions": {
      "get": {
        "description": "Every change to the balance, newest first, cursor-paged: grants (free credits), purchases, hourly usage roll-ups and adjustments. Per-request detail is in GET /v1/usage. Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "credit_transactions.list",
        "parameters": [
          {
            "description": "Only this kind.",
            "in": "query",
            "name": "type",
            "schema": {
              "enum": [
                "grant",
                "promo",
                "purchase",
                "plan",
                "usage",
                "adjustment"
              ],
              "type": "string"
            }
          },
          {
            "description": "Created at or after: RFC 3339 or a date (UTC).",
            "in": "query",
            "name": "since",
            "schema": {
              "maxLength": 40,
              "type": "string"
            }
          },
          {
            "description": "Created before: RFC 3339 or a date (UTC).",
            "in": "query",
            "name": "until",
            "schema": {
              "maxLength": 40,
              "type": "string"
            }
          },
          {
            "description": "Transactions per page (default 25, at most 100).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "balance_after": {
                            "description": "The ledger's balance after this transaction. Usage is recorded hourly, so the live balance (GET /v1/account) may be lower.",
                            "type": "integer"
                          },
                          "created_at": {
                            "description": "When it was recorded, RFC 3339 UTC.",
                            "format": "date-time",
                            "type": "string"
                          },
                          "credits": {
                            "description": "Credits added (positive) or spent (negative).",
                            "type": "integer"
                          },
                          "description": {
                            "description": "What it was, for humans.",
                            "type": "string"
                          },
                          "id": {
                            "description": "Transaction ID (ctx_…).",
                            "type": "string"
                          },
                          "object": {
                            "description": "Always credit_transaction.",
                            "enum": [
                              "credit_transaction"
                            ],
                            "type": "string"
                          },
                          "type": {
                            "description": "grant: free credits (signup) or a goodwill grant; promo: a promo code's credits; purchase: a credit pack; plan: a monthly plan's credits added, or what was left of them ended at renewal; usage: credits spent, rolled up per hour; adjustment: a correction by support, unspent credits of a refunded or disputed purchase taken back, or given back when a dispute is won. New values may be added.",
                            "enum": [
                              "grant",
                              "promo",
                              "purchase",
                              "plan",
                              "usage",
                              "adjustment"
                            ],
                            "type": "string"
                          }
                        },
                        "required": [
                          "object",
                          "id",
                          "type",
                          "credits",
                          "balance_after",
                          "description",
                          "created_at"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List credit transactions (the ledger)",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "List credit transactions (the ledger)",
        "tags": [
          "Account"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/events": {
      "get": {
        "description": "Every event of the account, newest first, whether or not a webhook endpoint received it: what webhooks would have delivered. Kept `events_retention_s` (30 days). Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "events.list",
        "parameters": [
          {
            "description": "Only events of this type (an event type, or a prefix wildcard such as job.*).",
            "in": "query",
            "name": "type",
            "schema": {
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "description": "Events per page (default and maximum 100).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page; omit to start from the newest.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "data": {
                            "description": "The type's data object (small: a summary plus links)."
                          },
                          "id": {
                            "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                            "type": "string"
                          },
                          "object": {
                            "description": "Always event.",
                            "enum": [
                              "event"
                            ],
                            "type": "string"
                          },
                          "timestamp": {
                            "description": "When it happened.",
                            "format": "date-time",
                            "type": "string"
                          },
                          "type": {
                            "description": "The event type (event types table); new types may be added.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "object",
                          "id",
                          "type",
                          "timestamp",
                          "data"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List events, newest first",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "List events, newest first",
        "tags": [
          "Events"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/events/{id}": {
      "get": {
        "description": "One event, as webhooks deliver it. Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "events.get",
        "parameters": [
          {
            "description": "Event ID (evt_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "data": {
                          "description": "The type's data object (small: a summary plus links)."
                        },
                        "id": {
                          "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always event.",
                          "enum": [
                            "event"
                          ],
                          "type": "string"
                        },
                        "timestamp": {
                          "description": "When it happened.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "type": {
                          "description": "The event type (event types table); new types may be added.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "type",
                        "timestamp",
                        "data"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get an event",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Get an event",
        "tags": [
          "Events"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/events/{id}/redeliver": {
      "post": {
        "description": "Queues a new delivery of the event (same `webhook-id`, so receivers deduplicate it) to one endpoint, or to every enabled endpoint subscribed to its type. The answer lists the deliveries queued (one page). Free.\n\n**Auth:** an API key with the `admin` scope, or the dashboard session.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "events.redeliver",
        "parameters": [
          {
            "description": "Event ID (evt_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "webhook_endpoint_id": {
                    "description": "Deliver to this endpoint only; default: every enabled endpoint subscribed to the event's type.",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "attempts": {
                            "description": "Attempts made so far.",
                            "type": "integer"
                          },
                          "created_at": {
                            "format": "date-time",
                            "type": "string"
                          },
                          "delivered_at": {
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "duration_ms": {
                            "description": "The last attempt's duration.",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "error": {
                            "description": "Why the last attempt failed when there was no response.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "event_id": {
                            "type": "string"
                          },
                          "event_type": {
                            "type": "string"
                          },
                          "id": {
                            "description": "whd_…",
                            "type": "string"
                          },
                          "next_attempt_at": {
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "object": {
                            "description": "Always webhook_delivery.",
                            "enum": [
                              "webhook_delivery"
                            ],
                            "type": "string"
                          },
                          "response_excerpt": {
                            "description": "The start of the last response body.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "description": "pending: an attempt is due (next_attempt_at). failed: every attempt failed, or the endpoint was disabled or deleted.",
                            "enum": [
                              "pending",
                              "succeeded",
                              "failed"
                            ],
                            "type": "string"
                          },
                          "status_code": {
                            "description": "The last attempt's HTTP status; null when it got none (timeout, refused, blocked URL).",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "webhook_endpoint_id": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "object",
                          "id",
                          "event_id",
                          "event_type",
                          "webhook_endpoint_id",
                          "status",
                          "attempts",
                          "status_code",
                          "duration_ms",
                          "response_excerpt",
                          "error",
                          "created_at",
                          "delivered_at",
                          "next_attempt_at"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Deliver an event again",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Deliver an event again",
        "tags": [
          "Events"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/facebook/ad": {
      "get": {
        "description": "Returns one ad from Meta's public Ad Library by its link or Library ID: its creatives, the days it ran, where it ran and who ran it. Each creative has its headline, text, link, call to action, images and videos, and the advertiser comes with its Page's likes, category, badge and linked Instagram account. Ads shown in the EU or the UK add the payer, beneficiary, targeting and reach by country, age and gender. Political and social-issue ads add Meta's impression, reach and spend ranges, and a branded content ad names its creator.\n\nReturns `{data, meta}`: `data` is a `Ad` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/ad/ (Markdown: https://socialtap.dev/docs/reference/facebook/ad/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/ad/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/ad/"
        },
        "operationId": "facebook.ad.get",
        "parameters": [
          {
            "description": "The ad's Meta Ad Library link (facebook.com/ads/library/?id=…), the official Ad Library API's ad_snapshot_url (facebook.com/ads/archive/render_ad/?id=…), or its Library ID.",
            "example": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=DE&id=1103375555695370&media_type=all",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The ad's Meta Ad Library link (facebook.com/ads/library/?id=…), the official Ad Library API's ad_snapshot_url (facebook.com/ads/archive/render_ad/?id=…), or its Library ID.",
              "examples": [
                "https://www.facebook.com/ads/library/?id=1448538159982118"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "advertiser": {
                          "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/792344054_2357663855066869_6663139051388824991_n.jpg?stp=dst-jpg_s60x60_tt6&_nc_cat=100&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&…",
                          "display_name": "Esso",
                          "id": "124748157936817",
                          "is_verified": false,
                          "url": "https://www.facebook.com/EssoDeutschland",
                          "username": "EssoDeutschland"
                        },
                        "approximate_fields": [
                          "country_codes",
                          "first_shown_at"
                        ],
                        "audience_size": null,
                        "country_codes": [
                          "DE"
                        ],
                        "creatives": [
                          {
                            "body": "Tanken, Snacks oder einen Kaffee? Das alles und viel mehr erwartet dich bei Esso.",
                            "cta_text": "Learn More",
                            "link_description": null,
                            "link_url": "https://www.esso.de/de-de/damit-fahren-wir-besser?utm_source=facebook&utm_medium=paidsocial&utm_campaign=masterbrand_2026_2hy&utm_term=backcourt&utm_content=1x1",
                            "media": [
                              {
                                "alt_text": null,
                                "duration_ms": null,
                                "expires_at": "2026-10-25T18:00:00Z",
                                "height": null,
                                "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/790643179_1059949036747222_1732898320488340543_n.jpg?_nc_cat=108&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&oe=F2A52380",
                                "type": "video",
                                "url": "https://video-atl3-1.xx.fbcdn.net/o1/v/t2/f2/m366/AQND9e-BMjtzqCZ0FbPblGYcGQ8j6vUBXYkHq85AodwUFgS3orA-sRXh9lT5UbtsmnSpwL_ot094eYeH8PrC-ESExk25IqvuuNNAuelnG27pCQ.mp4?_nc_cat=107&_nc_sid=SCRUBBED&_nc_ht=video-atl3-1.xx.fbcdn.net&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=SCRUBBE…",
                                "width": null
                              }
                            ],
                            "title": "Kraftstoff fürs Auto. Energie für dich."
                          },
                          {
                            "body": "Tanken, Snacks oder einen Kaffee? Das alles und viel mehr erwartet dich bei Esso.",
                            "cta_text": "Learn More",
                            "link_description": null,
                            "link_url": "https://www.esso.de/de-de/damit-fahren-wir-besser?utm_source=facebook&utm_medium=paidsocial&utm_campaign=masterbrand_2026_2hy&utm_term=backcourt&utm_content=1x1",
                            "media": [
                              {
                                "alt_text": null,
                                "duration_ms": null,
                                "expires_at": "2026-10-25T18:00:00Z",
                                "height": null,
                                "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/793483318_2138943053709897_6112027891760479229_n.jpg?_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&oe=F2A52380",
                                "type": "video",
                                "url": "https://video-atl3-1.xx.fbcdn.net/o1/v/t2/f2/m366/AQOafqMPVLeUIBX39JYn6sJ6wu5hquY_pveq5cGWgLn5xbkWjWgCf3pq3ti3P2iXiQZ-wnATW_Vp5elabdXMmVFrQaPqu88jW3VEEQj6J0hvaw.mp4?_nc_cat=103&_nc_sid=SCRUBBED&_nc_ht=video-atl3-1.xx.fbcdn.net&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=SCRUBBE…",
                                "width": null
                              }
                            ],
                            "title": "Kraftstoff fürs Auto. Energie für dich."
                          }
                        ],
                        "first_shown_at": "2026-09-07T07:00:00Z",
                        "id": "1103375555695370",
                        "impressions": null,
                        "is_active": true,
                        "is_political": false,
                        "languages": [],
                        "last_shown_at": null,
                        "paid_by": "Esso",
                        "platform": "facebook",
                        "platform_specific": {
                          "facebook": {
                            "advertiser_categories": [
                              "Energy Company"
                            ],
                            "advertiser_instagram": null,
                            "advertiser_instagram_follower_count": null,
                            "advertiser_like_count": 73755,
                            "beneficiary": "Esso",
                            "collation_count": null,
                            "collation_id": null,
                            "cta_type": "learn_more",
                            "impression_shares": null,
                            "is_advertiser_deleted": false,
                            "is_removed": false,
                            "is_synthetic": false,
                            "link_caption": "esso.de",
                            "partner": null,
                            "removal_reasons": [],
                            "special_ad_categories": [],
                            "targeting": [
                              {
                                "age_max": 65,
                                "age_min": 18,
                                "genders": [],
                                "locations": [
                                  {
                                    "is_excluded": false,
                                    "name": "Germany",
                                    "type": "countries"
                                  }
                                ],
                                "reach": 4974088,
                                "reach_by_country": [
                                  {
                                    "ages": [
                                      {
                                        "age_range": "18-24",
                                        "female": 175420,
                                        "male": 326568,
                                        "unknown": 9562
                                      },
                                      {
                                        "age_range": "Unknown",
                                        "female": 161,
                                        "male": 238,
                                        "unknown": 146
                                      },
                                      {
                                        "age_range": "65+",
                                        "female": 263221,
                                        "male": 309061,
                                        "unknown": 4425
                                      }
                                    ],
                                    "country_code": "DE"
                                  }
                                ],
                                "region": "eu"
                              }
                            ]
                          }
                        },
                        "publisher_platforms": [
                          "facebook",
                          "instagram"
                        ],
                        "reach": null,
                        "spend": null,
                        "type": "dynamic",
                        "unknown_fields": [
                          "languages"
                        ],
                        "url": "https://www.facebook.com/ads/library/?id=1103375555695370"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 756,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "ad",
                          "id": "1103375555695370",
                          "url": "https://www.facebook.com/ads/library/?id=1103375555695370"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookAdResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Creatives, run dates, placements and EU reach",
        "tags": [
          "Facebook Ad Library"
        ],
        "x-socialtap-endpoint": "facebook.ad",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "ad",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/ad_transcript": {
      "get": {
        "description": "Returns the timed transcript of a video ad from Meta's public Ad Library, by its link or Library ID, transcribed from the ad's audio. You get the full text, segments with their start and end times, the spoken language and the video's length. It works on single-video ads and on dynamic ads whose variations are videos, running or not.\n\nReturns `{data, meta}`: `data` is a `Transcript` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 2 credits + 2 per started minute of media per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/ad_transcript/ (Markdown: https://socialtap.dev/docs/reference/facebook/ad_transcript/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/ad_transcript/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/ad_transcript/"
        },
        "operationId": "facebook.ad_transcript.get",
        "parameters": [
          {
            "description": "The video ad's Meta Ad Library link (facebook.com/ads/library/?id=…), the official Ad Library API's ad_snapshot_url (facebook.com/ads/archive/render_ad/?id=…), or its Library ID.",
            "example": "https://www.facebook.com/ads/library/?id=1448538159982118",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The video ad's Meta Ad Library link (facebook.com/ads/library/?id=…), the official Ad Library API's ad_snapshot_url (facebook.com/ads/archive/render_ad/?id=…), or its Library ID.",
              "examples": [
                "https://www.facebook.com/ads/library/?id=1448538159982118"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language spoken in the video, a hint to speech-to-text. Without lang the language is detected.",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language spoken in the video, a hint to speech-to-text. Without lang the language is detected.",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "available_languages": [],
                        "duration_ms": 45489,
                        "id": "1448538159982118",
                        "is_auto_generated": true,
                        "language": "en",
                        "platform": "facebook",
                        "platform_specific": {},
                        "segments": [
                          {
                            "end_ms": 1940,
                            "start_ms": 0,
                            "text": "Open your clothes, open your clothes."
                          },
                          {
                            "end_ms": 3900,
                            "start_ms": 2340,
                            "text": "I know her name is Katie, hey Katie."
                          },
                          {
                            "end_ms": 5180,
                            "start_ms": 4200,
                            "text": "No more green beer."
                          }
                        ],
                        "source": "asr",
                        "text": "Open your clothes, open your clothes. I know her name is Katie, hey Katie. No more green beer. You do an Irish jig. Who in here knows who St. Patrick was? Green tea shot? No, it's St. Patty's Day or having Bailey's. It's just called a mini G shot. It's Bailey's Irish cream and co…",
                        "url": "https://www.facebook.com/ads/library/?id=1448538159982118"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "asr",
                        "is_cached": false,
                        "credits_charged": 4,
                        "latency_ms": 6131,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "ad",
                          "id": "1448538159982118",
                          "url": "https://www.facebook.com/ads/library/?id=1448538159982118"
                        },
                        "credits_remaining": 9996,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookAd_transcriptResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "no_transcript": {
                    "$ref": "#/components/examples/no_transcript"
                  },
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.\n\n`no_transcript`: The video or audio exists but has no transcript: no caption track and no speech to transcribe. Do not retry. If the platform offers other languages, try one with lang.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Timed transcript of what a video ad says",
        "tags": [
          "Facebook Ad Library"
        ],
        "x-socialtap-endpoint": "facebook.ad_transcript",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 122,
          "min_credits": 2,
          "prices": [
            {
              "credits": 2,
              "label": "2 credits + 2 per started minute of media",
              "max": 122,
              "per": 2,
              "source": "asr",
              "unit": "media_minute",
              "unit_max": 60
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "transcript",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/ads": {
      "get": {
        "description": "Returns the ads a Facebook Page ran on Facebook, Instagram, Messenger, Threads and the Audience Network, from its link, name or Page ID. Each ad from Meta's public Ad Library has the days it first and last ran, whether it's still active, where it ran and its creatives: headline, text, link, call to action, images and videos. Political and social-issue ads add the payer and Meta's impression, reach and spend ranges. Filter by country, language, status, kind of creative and dates, and sort by most impressions or newest.\n\nReturns `{data, page, meta}`: `data` holds up to 10 `Ad` items (the shared schema, the same on every platform), most impressions first with sort=popular (the default), most recently started first, in Meta's recency groups with sort=newest. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/ads/ (Markdown: https://socialtap.dev/docs/reference/facebook/ads/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/ads/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/ads/"
        },
        "operationId": "facebook.ads.list",
        "parameters": [
          {
            "description": "The advertiser: its Ad Library link (facebook.com/ads/library/?view_all_page_id=…), its Facebook Page's link or name, or its Page ID.",
            "example": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=ALL&view_all_page_id=20531316728&search_type=page&media_type=all",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The advertiser: its Ad Library link (facebook.com/ads/library/?view_all_page_id=…), its Facebook Page's link or name, or its Page ID.",
              "examples": [
                "https://www.facebook.com/ads/library/?view_all_page_id=20531316728&search_type=page"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only ads delivered in this country. All countries when omitted.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only ads delivered in this country. All countries when omitted.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). Only ads whose text Meta detects as this language (the primary subtag counts: pt-BR searches pt). All languages when omitted.",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). Only ads whose text Meta detects as this language (the primary subtag counts: pt-BR searches pt). All languages when omitted.",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items that are still running (active), only items that stopped (inactive), or both (all). Default: all.",
            "example": "active",
            "in": "query",
            "name": "status",
            "schema": {
              "default": "all",
              "description": "Only items that are still running (active), only items that stopped (inactive), or both (all). Default: all.",
              "enum": [
                "active",
                "inactive",
                "all"
              ],
              "examples": [
                "active"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only ads of this kind, as the Ad Library files them: image, video, meme (an image with text in it), image_and_meme (both) or text (no image or video). All kinds when omitted.",
            "example": "",
            "in": "query",
            "name": "format",
            "schema": {
              "description": "Only ads of this kind, as the Ad Library files them: image, video, meme (an image with text in it), image_and_meme (both) or text (no image or video). All kinds when omitted.",
              "enum": [
                "image",
                "video",
                "meme",
                "image_and_meme",
                "text"
              ],
              "type": "string"
            }
          },
          {
            "description": "Order of the results. popular (default): most impressions first, the Ad Library's own order. newest: the most recently started first, in Meta's recency groups, so not strictly by date.",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "popular",
              "description": "Order of the results. popular (default): most impressions first, the Ad Library's own order. newest: the most recently started first, in Meta's recency groups, so not strictly by date.",
              "enum": [
                "popular",
                "newest"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Ads count when they ran during the window: an ad that last ran (last_shown_at) before since is left out; active ads ran until today.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Ads count when they ran during the window: an ad that last ran (last_shown_at) before since is left out; active ads ran until today.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Ads count when they ran during the window: an ad that first ran (first_shown_at) at or after until is left out.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Ads count when they ran during the window: an ad that first ran (first_shown_at) at or after until is left out.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 10,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 10,
              "maximum": 10,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "advertiser": {
                            "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/444190414_420658830784969_8688257439109167735_n.jpg?stp=dst-jpg_s60x60_tt6&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&o…",
                            "display_name": "Facebook",
                            "id": "20531316728",
                            "is_verified": null,
                            "url": "https://www.facebook.com/facebook",
                            "username": "facebook"
                          },
                          "approximate_fields": [
                            "first_shown_at",
                            "impressions",
                            "last_shown_at"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": "Shop local businesses on Facebook Marketplace. Open now.",
                              "cta_text": "Use app",
                              "link_description": "Explore the things you love",
                              "link_url": "http://play.google.com/store/apps/details?id=com.facebook.katana",
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": null,
                                  "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.35426-6/441926459_1556801448238181_8589306082817029192_n.jpg?stp=dst-jpg_s600x600_tt6&_nc_cat=105&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBE…",
                                  "type": "image",
                                  "url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.35426-6/445002890_438029678859371_1806086145592848961_n.jpg?_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&oe=F2A52380",
                                  "width": null
                                }
                              ],
                              "title": "Shop Local on Marketplace"
                            }
                          ],
                          "first_shown_at": "2024-05-30T07:00:00Z",
                          "id": "1440659790146974",
                          "impressions": {
                            "lower_bound": 1000000,
                            "upper_bound": null
                          },
                          "is_active": false,
                          "is_political": true,
                          "languages": [],
                          "last_shown_at": "2024-10-18T07:00:00Z",
                          "paid_by": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "advertiser_categories": [
                                "Internet company"
                              ],
                              "advertiser_instagram": null,
                              "advertiser_instagram_follower_count": null,
                              "advertiser_like_count": 154921706,
                              "beneficiary": null,
                              "collation_count": 2,
                              "collation_id": "758420173028777",
                              "cta_type": "use_mobile_app",
                              "impression_shares": null,
                              "is_advertiser_deleted": false,
                              "is_removed": null,
                              "is_synthetic": false,
                              "link_caption": "play.google.com",
                              "partner": null,
                              "removal_reasons": [],
                              "special_ad_categories": [
                                "political"
                              ],
                              "targeting": []
                            }
                          },
                          "publisher_platforms": [
                            "instagram",
                            "audience_network"
                          ],
                          "reach": {
                            "lower_bound": 1000000,
                            "upper_bound": null
                          },
                          "spend": {
                            "currency": "USD",
                            "lower_bound": 250000,
                            "upper_bound": 299999
                          },
                          "type": "image",
                          "unknown_fields": [
                            "country_codes",
                            "languages",
                            "platform_specific.facebook.removal_reasons"
                          ],
                          "url": "https://www.facebook.com/ads/library/?id=1440659790146974"
                        },
                        {
                          "advertiser": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.35426-6/763761977_897297039659054_2373641633074239910_n.jpg?stp=dst-jpg_s60x60_tt6&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&o…",
                            "display_name": "Facebook",
                            "id": "20531316728",
                            "is_verified": null,
                            "url": "https://www.facebook.com/facebook",
                            "username": "facebook"
                          },
                          "approximate_fields": [
                            "first_shown_at"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": "Download Facebook and feed your passion for the outdoors with Groups.",
                              "cta_text": "Download",
                              "link_description": null,
                              "link_url": "http://play.google.com/store/apps/details?id=com.facebook.katana",
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": null,
                                  "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/767674769_2302540540500697_7951998685481294277_n.jpg?stp=dst-jpg_s600x600_tt6&_nc_cat=108&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBE…",
                                  "type": "image",
                                  "url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.35426-6/763980980_1026739123538638_5673970590546619705_n.jpg?_nc_cat=105&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&oe=F2A52380",
                                  "width": null
                                }
                              ],
                              "title": "Seek Adventures With Groups"
                            },
                            {
                              "body": "Download Facebook and feed your passion for the outdoors with Groups.",
                              "cta_text": "Download",
                              "link_description": null,
                              "link_url": "http://play.google.com/store/apps/details?id=com.facebook.katana",
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": null,
                                  "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/763895288_1853472159357870_8536681551954643843_n.jpg?stp=dst-jpg_s600x600_tt6&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBE…",
                                  "type": "image",
                                  "url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/764719922_1405143578194986_6948991656684682887_n.jpg?_nc_cat=107&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&oe=F2A52380",
                                  "width": null
                                }
                              ],
                              "title": "Seek Adventures With Groups"
                            },
                            {
                              "body": "Download Facebook and feed your passion for the outdoors with Groups.",
                              "cta_text": "Download",
                              "link_description": null,
                              "link_url": "http://play.google.com/store/apps/details?id=com.facebook.katana",
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": null,
                                  "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/767674769_2302540540500697_7951998685481294277_n.jpg?stp=dst-jpg_s600x600_tt6&_nc_cat=108&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBE…",
                                  "type": "image",
                                  "url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.35426-6/763980980_1026739123538638_5673970590546619705_n.jpg?_nc_cat=105&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&oe=F2A52380",
                                  "width": null
                                }
                              ],
                              "title": "Seek Adventures With Groups"
                            }
                          ],
                          "first_shown_at": "2026-10-06T07:00:00Z",
                          "id": "2253947551834151",
                          "impressions": null,
                          "is_active": true,
                          "is_political": false,
                          "languages": [],
                          "last_shown_at": null,
                          "paid_by": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "advertiser_categories": [
                                "Internet company"
                              ],
                              "advertiser_instagram": null,
                              "advertiser_instagram_follower_count": null,
                              "advertiser_like_count": 154921706,
                              "beneficiary": null,
                              "collation_count": 5,
                              "collation_id": "1065080066014280",
                              "cta_type": "download",
                              "impression_shares": null,
                              "is_advertiser_deleted": false,
                              "is_removed": null,
                              "is_synthetic": false,
                              "link_caption": "play.google.com",
                              "partner": null,
                              "removal_reasons": [],
                              "special_ad_categories": [],
                              "targeting": []
                            }
                          },
                          "publisher_platforms": [
                            "facebook",
                            "instagram",
                            "audience_network"
                          ],
                          "reach": null,
                          "spend": null,
                          "type": "dynamic",
                          "unknown_fields": [
                            "country_codes",
                            "languages",
                            "platform_specific.facebook.removal_reasons"
                          ],
                          "url": "https://www.facebook.com/ads/library/?id=2253947551834151"
                        },
                        {
                          "advertiser": {
                            "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/838939240_1390159663100311_7275738155822511390_n.jpg?stp=dst-jpg_s60x60_tt6&_nc_cat=106&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&…",
                            "display_name": "Facebook",
                            "id": "20531316728",
                            "is_verified": null,
                            "url": "https://www.facebook.com/facebook",
                            "username": "facebook"
                          },
                          "approximate_fields": [
                            "first_shown_at"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": "Discover new places with new people in Groups. Download Facebook.",
                              "cta_text": "Download",
                              "link_description": null,
                              "link_url": "http://play.google.com/store/apps/details?id=com.facebook.katana",
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": null,
                                  "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/837303193_2201269420433134_1772812502839754095_n.jpg?stp=dst-jpg_s600x600_tt6&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBE…",
                                  "type": "image",
                                  "url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/838612085_1104000178892017_4856035252372138746_n.jpg?_nc_cat=108&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&oe=F2A52380",
                                  "width": null
                                }
                              ],
                              "title": "See What's Out There in Groups"
                            }
                          ],
                          "first_shown_at": "2026-10-06T07:00:00Z",
                          "id": "1045014251929614",
                          "impressions": null,
                          "is_active": true,
                          "is_political": false,
                          "languages": [],
                          "last_shown_at": null,
                          "paid_by": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "advertiser_categories": [
                                "Internet company"
                              ],
                              "advertiser_instagram": null,
                              "advertiser_instagram_follower_count": null,
                              "advertiser_like_count": 154921706,
                              "beneficiary": null,
                              "collation_count": null,
                              "collation_id": null,
                              "cta_type": "download",
                              "impression_shares": null,
                              "is_advertiser_deleted": false,
                              "is_removed": null,
                              "is_synthetic": false,
                              "link_caption": "play.google.com",
                              "partner": null,
                              "removal_reasons": [],
                              "special_ad_categories": [],
                              "targeting": []
                            }
                          },
                          "publisher_platforms": [
                            "facebook",
                            "instagram",
                            "audience_network"
                          ],
                          "reach": null,
                          "spend": null,
                          "type": "image",
                          "unknown_fields": [
                            "country_codes",
                            "languages",
                            "platform_specific.facebook.removal_reasons"
                          ],
                          "url": "https://www.facebook.com/ads/library/?id=1045014251929614"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1708,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "20531316728",
                          "url": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=ALL&media_type=all&search_type=page&view_all_page_id=20531316728"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookAdsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Active and past ads of one Page, with creatives",
        "tags": [
          "Facebook Ad Library"
        ],
        "x-socialtap-endpoint": "facebook.ads",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "most impressions first",
          "orders": {
            "newest": "most recently started first, in Meta's recency groups",
            "popular": "most impressions first"
          },
          "page_max": 10,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "ad",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/comments": {
      "get": {
        "description": "Returns the top-level comments on a public Facebook post, photo, video or reel, most relevant or newest first, a page at a time. Each comment has its text, time, permalink, exact reaction count with the reactions by type, reply count, attached photo and whether the post's author wrote it, and the commenter's ID, name, profile link, picture and verified badge. It takes every link the Facebook Post API does.\n\nReturns `{data, page, meta}`: `data` holds up to 10 `Comment` items (the shared schema, the same on every platform), Facebook's All comments view: every top-level comment, the most relevant first with sort=relevance (the default), newest first with sort=newest. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/comments/ (Markdown: https://socialtap.dev/docs/reference/facebook/comments/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/comments/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/comments/"
        },
        "operationId": "facebook.comments.list",
        "parameters": [
          {
            "description": "Facebook post, photo, video or reel URL, as the Facebook Post API takes it: /<page>/posts/<id>, permalink.php and story.php links, /photo/?fbid= and /<page>/photos/… links, reel, watch, video.php and /<page>/videos/… links, fb.watch and /share/p|v|r/ share links (m., mbasic. and web. hosts too), or a numeric post, photo or video ID. A comment's link (?comment_id=) reads its post's comments.",
            "example": "https://www.facebook.com/cnn/posts/pfbid0zVcLXuYcv5N8D5oZn9NMU3R116cECPXJiKY6QyxiZGTA7eRDZb3zv3NkVwgC1GVdl",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Facebook post, photo, video or reel URL, as the Facebook Post API takes it: /<page>/posts/<id>, permalink.php and story.php links, /photo/?fbid= and /<page>/photos/… links, reel, watch, video.php and /<page>/videos/… links, fb.watch and /share/p|v|r/ share links (m., mbasic. and web. hosts too), or a numeric post, photo or video ID. A comment's link (?comment_id=) reads its post's comments.",
              "examples": [
                "https://www.facebook.com/cnn/posts/pfbid0zVcLXuYcv5N8D5oZn9NMU3R116cECPXJiKY6QyxiZGTA7eRDZb3zv3NkVwgC1GVdl"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. relevance (default): Facebook's All comments view, the most relevant first, including the comments its default view filters out. newest: every comment, newest first.",
            "example": "relevance",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "relevance",
              "description": "Order of the results. relevance (default): Facebook's All comments view, the most relevant first, including the comments its default view filters out. newest: every comment, newest first.",
              "enum": [
                "relevance",
                "newest"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 10,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 10,
              "maximum": 10,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/837402617_10240488748735344_2095546189445517301_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx720x720&ctp=s32x32&_nc_cat=100&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_…",
                            "display_name": "George Sampson",
                            "id": "pfbid0CYtKGzDDtxXk1PETorcSCFdSM2jxJF3XayHaezE6o8XMEa1APnAcVa4cHPnmyn4al",
                            "is_verified": false,
                            "url": null,
                            "username": null
                          },
                          "edited_at": null,
                          "id": "1134072982431001",
                          "is_by_post_author": null,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 39,
                            "reply_count": 12
                          },
                          "parent_id": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "author_gender": "male",
                              "image_url": null,
                              "reactions": [
                                {
                                  "count": 27,
                                  "type": "like"
                                },
                                {
                                  "count": 11,
                                  "type": "haha"
                                },
                                {
                                  "count": 1,
                                  "type": "love"
                                }
                              ]
                            }
                          },
                          "post_id": "1515533333772646",
                          "published_at": "2026-10-29T19:37:25Z",
                          "text": "Fox’s ratings are down substantially while MSNow and CNN are up.",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/cnn/posts/pfbid034UhZgwWAxAbbbqcVT6TLJQz9aGu17AWYtaZib2nUzN6ueQKyvyoBSJ1Ao4R7Aibzl?comment_id=1134072982431001"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t1.6435-1/38985115_2135903490004970_3576751264056213504_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx946x947&ctp=s32x32&_nc_cat=107&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_s…",
                            "display_name": "Michael Shelton",
                            "id": "pfbid0HyC8RVyhaoZG7evfeukYuTnh5Q87tU6ACBtTFbpvvGmXLVLAN2au52Vdk3DnKndBl",
                            "is_verified": false,
                            "url": "https://www.facebook.com/michael.shelton.528",
                            "username": "michael.shelton.528"
                          },
                          "edited_at": null,
                          "id": "2366768057490102",
                          "is_by_post_author": null,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 20,
                            "reply_count": 2
                          },
                          "parent_id": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "author_gender": "male",
                              "image_url": null,
                              "reactions": [
                                {
                                  "count": 20,
                                  "type": "like"
                                }
                              ]
                            }
                          },
                          "post_id": "1515533333772646",
                          "published_at": "2026-10-29T19:53:16Z",
                          "text": "An equally interesting question is what will CNN look like.",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/cnn/posts/pfbid034UhZgwWAxAbbbqcVT6TLJQz9aGu17AWYtaZib2nUzN6ueQKyvyoBSJ1Ao4R7Aibzl?comment_id=2366768057490102"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/511906991_24085412141097078_6841766951798215929_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx648x648&ctp=s32x32&_nc_cat=107&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_…",
                            "display_name": "Steve Jenkins",
                            "id": "pfbid02tWsPGdCcwsR9MDGBfyqw45aVVh34i1ZxbmHZ41TniRyXx4VMoQAmgt2ikBy1fTLql",
                            "is_verified": false,
                            "url": "https://www.facebook.com/people/Steve-Jenkins/pfbid02tWsPGdCcwsR9MDGBfyqw45aVVh34i1ZxbmHZ41TniRyXx4VMoQAmgt2ikBy1fTLql/",
                            "username": null
                          },
                          "edited_at": null,
                          "id": "2241840356745830",
                          "is_by_post_author": null,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 4,
                            "reply_count": 5
                          },
                          "parent_id": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "author_gender": "male",
                              "image_url": null,
                              "reactions": [
                                {
                                  "count": 4,
                                  "type": "like"
                                }
                              ]
                            }
                          },
                          "post_id": "1515533333772646",
                          "published_at": "2026-10-29T22:21:23Z",
                          "text": "I have noticed that Fox is reporting more truthfully meaning showing Trump's negative numbers, etc.",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/cnn/posts/pfbid034UhZgwWAxAbbbqcVT6TLJQz9aGu17AWYtaZib2nUzN6ueQKyvyoBSJ1Ao4R7Aibzl?comment_id=2241840356745830"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 825,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "1515533333772646",
                          "url": "https://www.facebook.com/cnn/posts/pfbid034UhZgwWAxAbbbqcVT6TLJQz9aGu17AWYtaZib2nUzN6ueQKyvyoBSJ1Ao4R7Aibzl"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookCommentsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Top-level, with exact reactions and reply counts",
        "tags": [
          "Facebook"
        ],
        "x-socialtap-endpoint": "facebook.comments",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Facebook's All comments view: every top-level comment, the most relevant first",
          "orders": {
            "newest": "newest first",
            "relevance": "Facebook's All comments view: every top-level comment, the most relevant first"
          },
          "page_max": 10,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/engagement": {
      "get": {
        "description": "Returns a public Facebook Page's or person's engagement rate and post stats, computed over its latest posts in one request. You get engagement rate per follower and per view (mean, median and spread), likes, comments and shares per post, views per video, comment-to-like ratio, posting cadence, the mix of photos, videos and reels, and the top and bottom post. The profile and each post come with it, with exact counts and each post's rate against the account's typical post. Send a name, ID or link.\n\nReturns `{data, meta}`: `data` is a `Engagement` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/engagement/ (Markdown: https://socialtap.dev/docs/reference/facebook/engagement/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/engagement/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/engagement/"
        },
        "operationId": "facebook.engagement.get",
        "parameters": [
          {
            "description": "The Facebook profile (a Page's or a person's): its vanity name (NASA, case-insensitive), its numeric profile ID or Page ID, or any link to it: facebook.com/<name> with any tab after it, profile.php?id=…, /people/<name>/<id>, /p/<name>-<id>, /pages/category/…, fb.me/<name>.",
            "example": "NASA",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Facebook profile (a Page's or a person's): its vanity name (NASA, case-insensitive), its numeric profile ID or Page ID, or any link to it: facebook.com/<name> with any tab after it, profile.php?id=…, /people/<name>/<id>, /p/<name>-<id>, /pages/category/…, fb.me/<name>.",
              "examples": [
                "NASA"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "bottom_post_id": "1676179567210746",
                        "id": "100044561550831",
                        "metrics": {
                          "comment_to_like_ratio": 0.017837,
                          "comments_per_post": 54,
                          "counted_post_count": 3,
                          "engagement_rate": 0.000107,
                          "engagement_rate_stddev": 0.00014,
                          "formats": [
                            {
                              "counted_post_count": 2,
                              "engagement_rate": 0.000158,
                              "interactions_per_post": 4527.5,
                              "type": "image",
                              "views_per_post": null
                            },
                            {
                              "counted_post_count": 1,
                              "engagement_rate": 0.000007,
                              "interactions_per_post": 189,
                              "type": "text",
                              "views_per_post": null
                            }
                          ],
                          "interactions_per_post": 3081.33,
                          "likes_per_post": 3027.33,
                          "median_engagement_rate": 0.00001,
                          "median_views_per_post": null,
                          "posts_per_week": 16.03,
                          "quotes_per_post": null,
                          "rated_post_count": 3,
                          "reposts_per_post": null,
                          "sampled_post_count": 3,
                          "saves_per_post": null,
                          "shares_per_post": 214.33,
                          "view_engagement_rate": null,
                          "views_per_post": null
                        },
                        "newest_post_at": "2026-11-03T19:27:52Z",
                        "oldest_post_at": "2026-11-02T22:30:00Z",
                        "platform": "facebook",
                        "platform_specific": {},
                        "posts": [
                          {
                            "engagement_rate": 0.000007,
                            "engagement_vs_median": 0.66,
                            "is_counted": true,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/243095782_416661036495945_3843362260429099279_n.png?stp=cp0_dst-png&cstp=mx800x800&ctp=s80x80&_nc_cat=108&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=…",
                                "display_name": "NASA - National Aeronautics and Space Administration",
                                "id": "100044561550831",
                                "is_verified": true,
                                "url": "https://www.facebook.com/NASA",
                                "username": "NASA"
                              },
                              "coauthors": [],
                              "duration_ms": null,
                              "hashtags": [],
                              "id": "1676179567210746",
                              "is_nsfw": null,
                              "is_pinned": null,
                              "is_sponsored": null,
                              "language": null,
                              "media": [],
                              "mentions": [],
                              "metrics": {
                                "comment_count": 10,
                                "like_count": 179,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": null,
                                "share_count": 6,
                                "view_count": null
                              },
                              "platform": "facebook",
                              "platform_specific": {
                                "facebook": {
                                  "feedback_id": "ZmVlZGJhY2s6cGZiaWQwMmlSQkFpeENQd1R1Zml6aUFWTXZRdWEzTEJuZHk2dGYzUHl2NDE1UWtaZjdGdjdneTM1U2VpRVltN3Z0UGNMcGps",
                                  "group": null,
                                  "is_attachment_unavailable": false,
                                  "link": null,
                                  "listing": null,
                                  "music": null,
                                  "reactions": [
                                    {
                                      "count": 155,
                                      "type": "like"
                                    },
                                    {
                                      "count": 22,
                                      "type": "love"
                                    },
                                    {
                                      "count": 1,
                                      "type": "care"
                                    }
                                  ],
                                  "shared_post": {
                                    "author": {
                                      "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/516872204_1189959146491994_4245240435554141606_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx2048x2047&ctp=s80x80&_nc_cat=103&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&…",
                                      "display_name": "Learn With NASA",
                                      "id": "100064337605401",
                                      "is_verified": true,
                                      "url": "https://www.facebook.com/LearnWithNASA",
                                      "username": "LearnWithNASA"
                                    },
                                    "id": "1615866537234584",
                                    "url": "https://www.facebook.com/LearnWithNASA/posts/pfbid0qRf3ZGacva8hj6xVFVrBA29EF3mMnZGmcG6zYUaeLRB1yHARL2KHoPFaqH5jM72yl"
                                  },
                                  "video_id": null
                                }
                              },
                              "platform_type": "post",
                              "published_at": "2026-11-03T19:27:52Z",
                              "text": null,
                              "thumbnail_url": null,
                              "title": null,
                              "type": "text",
                              "unknown_fields": [],
                              "url": "https://www.facebook.com/NASA/posts/pfbid02iRBAixCPwTufiziAVMvQua3LBndy6tf3Pyv415QkZf7Fv7gy35SeiEYm7vtPcLpjl"
                            },
                            "view_engagement_rate": null,
                            "views_vs_median": null
                          },
                          {
                            "engagement_rate": 0.000305,
                            "engagement_vs_median": 30.55,
                            "is_counted": true,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/243095782_416661036495945_3843362260429099279_n.png?stp=cp0_dst-png&cstp=mx800x800&ctp=s80x80&_nc_cat=108&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=…",
                                "display_name": "NASA - National Aeronautics and Space Administration",
                                "id": "100044561550831",
                                "is_verified": true,
                                "url": "https://www.facebook.com/NASA",
                                "username": "NASA"
                              },
                              "coauthors": [],
                              "duration_ms": null,
                              "hashtags": [],
                              "id": "1675983783896991",
                              "is_nsfw": null,
                              "is_pinned": null,
                              "is_sponsored": null,
                              "language": null,
                              "media": [
                                {
                                  "alt_text": "An intricate cloud of white dust takes center stage in this photo, rising in a windy pillar. The background features rust-colored dust with dots of distant stars and galaxies shining through.",
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": 1385,
                                  "thumbnail_url": null,
                                  "type": "image",
                                  "url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/871223884_1487536193225483_3660942795677810580_n.png?stp=dst-jpg_tt6&cstp=mx2000x1385&ctp=s2000x1385&_nc_cat=101&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&…",
                                  "width": 2000
                                }
                              ],
                              "mentions": [
                                "NASAWebb"
                              ],
                              "metrics": {
                                "comment_count": 134,
                                "like_count": 8634,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": null,
                                "share_count": 606,
                                "view_count": null
                              },
                              "platform": "facebook",
                              "platform_specific": {
                                "facebook": {
                                  "feedback_id": "ZmVlZGJhY2s6cGZiaWQwZDJ3bUtXZm9Lc1Q5d0s5bndvV1c1SHpzRWd2MjhjSno5UTZuUDVBMjZCTGNrdVFlQWJCWnNQM0RuSm1pU2s3Q2w=",
                                  "group": null,
                                  "is_attachment_unavailable": false,
                                  "link": null,
                                  "listing": null,
                                  "music": null,
                                  "reactions": [
                                    {
                                      "count": 4819,
                                      "type": "like"
                                    },
                                    {
                                      "count": 3553,
                                      "type": "love"
                                    },
                                    {
                                      "count": 148,
                                      "type": "care"
                                    }
                                  ],
                                  "shared_post": null,
                                  "video_id": null
                                }
                              },
                              "platform_type": "post",
                              "published_at": "2026-11-03T15:00:35Z",
                              "text": "Pspsps 🐈‍⬛\n\nThis smoky specter is the Cat’s Head Nebula, captured in intricate detail by NASA's James Webb Space Telescope. Its name comes from its shape, which resembles a cosmic kitty sitting with its back toward the viewer. What do you see?",
                              "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/871223884_1487536193225483_3660942795677810580_n.png?stp=dst-jpg_tt6&cstp=mx2000x1385&ctp=s2000x1385&_nc_cat=101&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&…",
                              "title": null,
                              "type": "image",
                              "unknown_fields": [],
                              "url": "https://www.facebook.com/NASA/posts/pfbid0d2wmKWfoKsT9wK9nwoWW5HzsEgv28cJz9Q6nP5A26BLckuQeAbBZsP3DnJmiSk7Cl"
                            },
                            "view_engagement_rate": null,
                            "views_vs_median": null
                          },
                          {
                            "engagement_rate": 0.00001,
                            "engagement_vs_median": 1,
                            "is_counted": true,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/243095782_416661036495945_3843362260429099279_n.png?stp=cp0_dst-png&cstp=mx800x800&ctp=s80x80&_nc_cat=108&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=…",
                                "display_name": "NASA - National Aeronautics and Space Administration",
                                "id": "100044561550831",
                                "is_verified": true,
                                "url": "https://www.facebook.com/NASA",
                                "username": "NASA"
                              },
                              "coauthors": [],
                              "duration_ms": null,
                              "hashtags": [],
                              "id": "1675279183967451",
                              "is_nsfw": null,
                              "is_pinned": null,
                              "is_sponsored": null,
                              "language": null,
                              "media": [
                                {
                                  "alt_text": "An image that shows the \"MAX POWER Kennedy Space Center\" app as it appears in the iOS App Store.",
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": 1294,
                                  "thumbnail_url": null,
                                  "type": "image",
                                  "url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/864280748_2020097565352172_6759494451320615303_n.png?stp=dst-jpg_tt6&cstp=mx2048x1294&ctp=s2048x1294&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&…",
                                  "width": 2048
                                }
                              ],
                              "mentions": [],
                              "metrics": {
                                "comment_count": 18,
                                "like_count": 269,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": null,
                                "share_count": 31,
                                "view_count": null
                              },
                              "platform": "facebook",
                              "platform_specific": {
                                "facebook": {
                                  "feedback_id": "ZmVlZGJhY2s6cGZiaWQwMnBqYUxiZmhBbkZtckRvb254eDdHeWVwVDFIN3BGYmk5d3JwcXF1TDZvTTVnVFVKYmZCRTJCVDJYY2h0RzkzcjJs",
                                  "group": null,
                                  "is_attachment_unavailable": false,
                                  "link": null,
                                  "listing": null,
                                  "music": null,
                                  "reactions": [
                                    {
                                      "count": 231,
                                      "type": "like"
                                    },
                                    {
                                      "count": 30,
                                      "type": "love"
                                    },
                                    {
                                      "count": 5,
                                      "type": "care"
                                    }
                                  ],
                                  "shared_post": null,
                                  "video_id": null
                                }
                              },
                              "platform_type": "post",
                              "published_at": "2026-11-02T22:30:00Z",
                              "text": "Planning your trip to MAX POWER? We've got a tool for that.\n\nEvent schedules, maps, and FAQs are at your fingertips with the MAX POWER app. It's free and available to download from official app stores on iOS and Android devices: https://go.nasa.gov/3V2iiWX",
                              "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/864280748_2020097565352172_6759494451320615303_n.png?stp=dst-jpg_tt6&cstp=mx2048x1294&ctp=s2048x1294&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&…",
                              "title": null,
                              "type": "image",
                              "unknown_fields": [],
                              "url": "https://www.facebook.com/NASA/posts/pfbid02pjaLbfhAnFmrDoonxx7GyepT1H7pFbi9wrpqquL6oM5gTUJbfBE2BT2XchtG93r2l"
                            },
                            "view_engagement_rate": null,
                            "views_vs_median": null
                          }
                        ],
                        "profile": {
                          "approximate_fields": [],
                          "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/243095782_416661036495945_3843362260429099279_n.png?stp=dst-png&cstp=mx800x800&ctp=s800x800&_nc_cat=108&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b…",
                          "banner_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.99422-6/809146614_4484013928506139_3181913787670602881_n.png?stp=dst-jpg_tt6&cstp=mx2047x1487&ctp=s2047x1487&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&…",
                          "bio": "Explore the universe and discover our home planet. \nThere's space for everybody. ✨",
                          "category": "Government organization",
                          "country_code": null,
                          "created_at": "2009-03-04T21:45:25Z",
                          "display_name": "NASA - National Aeronautics and Space Administration",
                          "external_links": [
                            {
                              "title": "nasa.gov/nasa-app",
                              "url": "https://www.nasa.gov/nasa-app/"
                            },
                            {
                              "title": "nasa.gov",
                              "url": "https://www.nasa.gov/"
                            }
                          ],
                          "id": "100044561550831",
                          "is_private": null,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": 28732202,
                            "following_count": 52,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "ad_library_entity_type": null,
                              "admin_countries": [
                                {
                                  "count": 15,
                                  "country": "United States"
                                }
                              ],
                              "alternate_name": null,
                              "business_hours": [],
                              "education": [],
                              "email": "public-inquiries@hq.nasa.gov",
                              "gender": null,
                              "hometown": null,
                              "hours_status": null,
                              "instagram_follower_count": null,
                              "instagram_username": null,
                              "is_deleted": null,
                              "is_instagram_verified": null,
                              "is_memorialized": false,
                              "is_political_advertiser": false,
                              "is_running_ads": false,
                              "name_changes": [
                                {
                                  "changed_at": "2014-04-07T19:49:21Z",
                                  "name": "NASA - National Aeronautics and Space Administration"
                                }
                              ],
                              "owner_location": "WASHINGTON DC, 20024 United States of America",
                              "owner_name": "NATIONAL AERONAUTICS AND SPACE ADMINISTRATION",
                              "page_id": "54971236771",
                              "phone": null,
                              "price_range": null,
                              "rating": null,
                              "recommend_percent": null,
                              "relationship": null,
                              "review_count": null,
                              "services": [],
                              "talking_about_count": null,
                              "were_here_count": null,
                              "work": []
                            }
                          },
                          "type": "organization",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/NASA",
                          "username": "NASA"
                        },
                        "top_post_id": "1675983783896991",
                        "unknown_fields": [],
                        "url": "https://www.facebook.com/NASA"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 2283,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "100044561550831",
                          "url": "https://www.facebook.com/NASA"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookEngagementResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Engagement rate, cadence and top posts",
        "tags": [
          "Facebook"
        ],
        "x-socialtap-endpoint": "facebook.engagement",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "engagement",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/event": {
      "get": {
        "description": "Returns a public Facebook event from its link or ID: name, description, start and end, venue, hosts, and exact going and interested counts. It also has whether it's scheduled, under way, over or canceled, its offset from UTC, whether it's online, the venue's address, city and coordinates, the cover, categories, ticket link, seller and price label, the group it was created in, and for a date of a recurring event its series and how many dates that has.\n\nReturns `{data, meta}`: `data` is a `Event` object (the shared schema, the same on every platform). Null means unknown.\n\nIn Facebook's words: `metrics.attendee_count` is going.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/event/ (Markdown: https://socialtap.dev/docs/reference/facebook/event/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/event/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/event/"
        },
        "operationId": "facebook.event.get",
        "parameters": [
          {
            "description": "The event's Facebook link (facebook.com/events/<id>/, with its slugged form /events/<venue>/<name>/<id>/, a date of a series /events/<series>/<date>/ or ?event_time_id=<date>, or the legacy event.php?eid=<id>; m. and web. hosts too) or its numeric ID.",
            "example": "https://www.facebook.com/events/jannus-live/arch-enemy-the-black-dahlia-murder-wrath-across-north-america-2026/2513378022457980/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The event's Facebook link (facebook.com/events/<id>/, with its slugged form /events/<venue>/<name>/<id>/, a date of a series /events/<series>/<date>/ or ?event_time_id=<date>, or the legacy event.php?eid=<id>; m. and web. hosts too) or its numeric ID.",
              "examples": [
                "https://www.facebook.com/events/2513378022457980/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "categories": [
                          "Music & audio"
                        ],
                        "community_id": null,
                        "cover_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-6/701643646_1454949970006889_5222368129042891587_n.avif?stp=dst-jpg_tt6&cstp=mx2048x1152&ctp=s2048x1152&_nc_cat=105&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED…",
                        "description": "Arch Enemy & The Black Dahlia Murder will be performing at Jannus Live on Sunday, October 18th. This event is All Ages. Doors open at 5:00 PM, Show starts at 6:00 PM. All support acts are subject to change without notice. This event is rain or shine.\n\nSale Dates and Times:\n\nPubli…",
                        "end_at": null,
                        "hosts": [
                          {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/703461784_1493244248837311_492679311377568321_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx1080x1080&ctp=s74x74&_nc_cat=104&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_…",
                            "display_name": "Thrown Into Exile",
                            "id": "100044552494354",
                            "is_verified": true,
                            "url": "https://www.facebook.com/ThrownIntoExile",
                            "username": "ThrownIntoExile"
                          },
                          {
                            "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/481358765_1074963661337894_2872436054536647170_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx1024x1024&ctp=s74x74&_nc_cat=103&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&…",
                            "display_name": "No Clubs",
                            "id": "100064728099080",
                            "is_verified": false,
                            "url": "https://www.facebook.com/Noclubsproductions",
                            "username": "Noclubsproductions"
                          },
                          {
                            "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/302197946_452479626918288_252645739401521140_n.png?stp=cp0_dst-png&cstp=mx200x200&ctp=s74x74&_nc_cat=106&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7…",
                            "display_name": "Jannus Live",
                            "id": "100064687631616",
                            "is_verified": false,
                            "url": "https://www.facebook.com/jannuslive",
                            "username": "jannuslive"
                          }
                        ],
                        "id": "2513378022457980",
                        "is_online": false,
                        "metrics": {
                          "attendee_count": 52
                        },
                        "name": "Arch Enemy & The Black Dahlia Murder: Wrath Across North America 2026",
                        "parent_id": null,
                        "place": {
                          "address": "201 Central Ave, St Petersburg, FL 33701-3325, United States",
                          "city": "Saint Petersburg, Florida",
                          "country_code": null,
                          "id": null,
                          "latitude": 27.771757351792,
                          "longitude": -82.636019393897,
                          "name": "Jannus Live",
                          "url": null
                        },
                        "platform": "facebook",
                        "platform_specific": {
                          "facebook": {
                            "city_id": "111326725552547",
                            "date_text": "Sunday, October 18, 2026 at 5:00 PM EDT",
                            "frequency": "single",
                            "metrics": {
                              "interested_count": 355,
                              "response_count": 407
                            },
                            "occurrence_count": 0,
                            "price_text": null,
                            "ticket_provider": null
                          }
                        },
                        "start_at": "2026-10-18T21:00:00Z",
                        "status": "ended",
                        "ticket_url": null,
                        "time_zone": null,
                        "unknown_fields": [],
                        "url": "https://www.facebook.com/events/2513378022457980/",
                        "utc_offset_minutes": -240
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 866,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "event",
                          "id": "2513378022457980",
                          "url": "https://www.facebook.com/events/2513378022457980/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookEventResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Date, venue, hosts and exact RSVP counts",
        "tags": [
          "Facebook Events"
        ],
        "x-socialtap-endpoint": "facebook.event",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "event",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/events": {
      "get": {
        "description": "Returns the public events on a Facebook Page's or person's Events tab, upcoming or past, from a vanity name, profile ID or profile link. Each event has its name, whether it's scheduled, under way, over or canceled, its start time with its offset from UTC, whether it's online, its venue and city, its cover and who hosts it. Narrow them by date with since and until.\n\nReturns `{data, page, meta}`: `data` holds up to 8 `Event` items (the shared schema, the same on every platform), oldest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Facebook's words: `metrics.attendee_count` is going.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/events/ (Markdown: https://socialtap.dev/docs/reference/facebook/events/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/events/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/events/"
        },
        "operationId": "facebook.events.list",
        "parameters": [
          {
            "description": "The Facebook profile (a Page's or a person's): its vanity name (jannuslive, case-insensitive), its numeric profile ID, or any link to it: facebook.com/<name> with any tab after it, profile.php?id=…, /people/<name>/<id>, /p/<name>-<id>.",
            "example": "jannuslive",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Facebook profile (a Page's or a person's): its vanity name (jannuslive, case-insensitive), its numeric profile ID, or any link to it: facebook.com/<name> with any tab after it, profile.php?id=…, /people/<name>/<id>, /p/<name>-<id>.",
              "examples": [
                "jannuslive"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Which events: upcoming, soonest first (events under way included); past, latest first, as the profile's Events tab shows them.",
            "example": "",
            "in": "query",
            "name": "time",
            "schema": {
              "default": "upcoming",
              "description": "Which events: upcoming, soonest first (events under way included); past, latest first, as the profile's Events tab shows them.",
              "enum": [
                "upcoming",
                "past"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only events starting at or after this time.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only events starting at or after this time.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Only events starting before this time.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Only events starting before this time.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 8,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 8,
              "maximum": 8,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "categories": [],
                          "community_id": null,
                          "cover_url": "https://scontent-hou1-1.xx.fbcdn.net/v/t39.30808-6/689010503_1426152826217625_6518170320015938469_n.jpg?stp=c145.0.910.628a_dst-jpg_tt6&cstp=mx910x628&ctp=s235x165&_nc_cat=105&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-hou1-1.xx&_nc_g…",
                          "description": null,
                          "end_at": null,
                          "hosts": [
                            {
                              "avatar_url": null,
                              "display_name": "Jannus Live",
                              "id": "100064687631616",
                              "is_verified": false,
                              "url": "https://www.facebook.com/jannuslive",
                              "username": "jannuslive"
                            }
                          ],
                          "id": "1195651112570986",
                          "is_online": false,
                          "metrics": {
                            "attendee_count": null
                          },
                          "name": "MOVEMENTS - HAPPIER NOW USA TOUR",
                          "parent_id": null,
                          "place": {
                            "address": null,
                            "city": "St Petersburg",
                            "country_code": null,
                            "id": null,
                            "latitude": null,
                            "longitude": null,
                            "name": "200 1st Ave N, Saint Petersburg, FL, United States, Florida 33701",
                            "url": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "city_id": null,
                              "date_text": "Wed, Nov 4 at 6:00 PM EST",
                              "frequency": null,
                              "metrics": {
                                "interested_count": null,
                                "response_count": null
                              },
                              "occurrence_count": null,
                              "price_text": null,
                              "ticket_provider": null
                            }
                          },
                          "start_at": "2026-11-04T23:00:00Z",
                          "status": "scheduled",
                          "ticket_url": null,
                          "time_zone": null,
                          "unknown_fields": [
                            "categories"
                          ],
                          "url": "https://www.facebook.com/events/1195651112570986/",
                          "utc_offset_minutes": -300
                        },
                        {
                          "approximate_fields": [],
                          "categories": [],
                          "community_id": null,
                          "cover_url": "https://scontent-hou1-1.xx.fbcdn.net/v/t39.99422-6/752022562_3213771052163800_3772178195491863544_n.png?stp=c189.0.1670.1152a_dst-jpg_tt6&cstp=mx1670x1152&ctp=s235x165&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-hou1-1.xx&_…",
                          "description": null,
                          "end_at": null,
                          "hosts": [
                            {
                              "avatar_url": null,
                              "display_name": "Jannus Live",
                              "id": "100064687631616",
                              "is_verified": false,
                              "url": "https://www.facebook.com/jannuslive",
                              "username": "jannuslive"
                            }
                          ],
                          "id": "1007777452102015",
                          "is_online": false,
                          "metrics": {
                            "attendee_count": null
                          },
                          "name": "TRIVIUM: CROWN IN THE GRAVE WORLD TOUR",
                          "parent_id": null,
                          "place": {
                            "address": null,
                            "city": "St Petersburg",
                            "country_code": null,
                            "id": "345248550607",
                            "latitude": null,
                            "longitude": null,
                            "name": "Jannus Live",
                            "url": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "city_id": null,
                              "date_text": "Thu, Nov 5 at 5:30 PM EST",
                              "frequency": null,
                              "metrics": {
                                "interested_count": null,
                                "response_count": null
                              },
                              "occurrence_count": null,
                              "price_text": null,
                              "ticket_provider": null
                            }
                          },
                          "start_at": "2026-11-05T22:30:00Z",
                          "status": "scheduled",
                          "ticket_url": null,
                          "time_zone": null,
                          "unknown_fields": [
                            "categories"
                          ],
                          "url": "https://www.facebook.com/events/1007777452102015/",
                          "utc_offset_minutes": -300
                        },
                        {
                          "approximate_fields": [],
                          "categories": [],
                          "community_id": null,
                          "cover_url": "https://scontent-hou1-1.xx.fbcdn.net/v/t39.30808-6/725547215_1482760040559215_5316960699790543595_n.avif?stp=c34.0.1980.1365a_dst-jpg_tt6&cstp=mx1980x1365&ctp=s235x165&_nc_cat=101&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-hou1-1.xx&_…",
                          "description": null,
                          "end_at": null,
                          "hosts": [
                            {
                              "avatar_url": null,
                              "display_name": "Jannus Live",
                              "id": "100064687631616",
                              "is_verified": false,
                              "url": "https://www.facebook.com/jannuslive",
                              "username": "jannuslive"
                            }
                          ],
                          "id": "1319224153724613",
                          "is_online": false,
                          "metrics": {
                            "attendee_count": null
                          },
                          "name": "Greensky Bluegrass",
                          "parent_id": null,
                          "place": {
                            "address": null,
                            "city": "St Petersburg",
                            "country_code": null,
                            "id": "345248550607",
                            "latitude": null,
                            "longitude": null,
                            "name": "Jannus Live",
                            "url": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "city_id": null,
                              "date_text": "Fri, Nov 6 at 6:30 PM EST",
                              "frequency": null,
                              "metrics": {
                                "interested_count": null,
                                "response_count": null
                              },
                              "occurrence_count": null,
                              "price_text": null,
                              "ticket_provider": null
                            }
                          },
                          "start_at": "2026-11-06T23:30:00Z",
                          "status": "scheduled",
                          "ticket_url": null,
                          "time_zone": null,
                          "unknown_fields": [
                            "categories"
                          ],
                          "url": "https://www.facebook.com/events/1319224153724613/",
                          "utc_offset_minutes": -300
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 841,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "100064687631616",
                          "url": "https://www.facebook.com/jannuslive"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookEventsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Upcoming and past events a Page or person hosts",
        "tags": [
          "Facebook Events"
        ],
        "x-socialtap-endpoint": "facebook.events",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "oldest first",
          "page_max": 8,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "event",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/group": {
      "get": {
        "description": "Returns a Facebook group's about page from its link or ID: exact member count, description, privacy, rules, posting activity and who runs it. It also has the name and vanity name, cover photo and picture, whether the group shows in search, its topics and location, when it was created and its name changes, each admin's and moderator's name, picture and profile link, and the Page it belongs to. Private groups answer too, with what their page shows logged out.\n\nReturns `{data, meta}`: `data` is a `Community` object (Facebook calls it a group) (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/group/ (Markdown: https://socialtap.dev/docs/reference/facebook/group/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/group/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/group/"
        },
        "operationId": "facebook.group.get",
        "parameters": [
          {
            "description": "The group: its link (facebook.com/groups/<ID or name>, any tab of it, on any facebook.com host; the legacy group.php?gid=<ID>), its share link (facebook.com/share/g/<code>) or its bare numeric ID.",
            "example": "https://www.facebook.com/groups/366190054572553/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The group: its link (facebook.com/groups/<ID or name>, any tab of it, on any facebook.com host; the legacy group.php?gid=<ID>), its share link (facebook.com/share/g/<code>) or its bare numeric ID.",
              "examples": [
                "https://www.facebook.com/groups/366190054572553/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t1.6435-9/121615771_3201454343306997_2348901429098757975_n.jpg?stp=c120.0.400.400a_cp0_dst-jpg_tt6&cstp=mx400x400&ctp=s110x80&_nc_cat=106&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.xx&_nc_…",
                        "banner_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t1.6435-9/121615771_3201454343306997_2348901429098757975_n.jpg?stp=dst-jpg_tt6&cstp=mx640x400&ctp=s640x400&_nc_cat=106&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss…",
                        "categories": [
                          "Software & tech",
                          "Engineering"
                        ],
                        "created_at": "2020-10-14T11:05:03Z",
                        "description": "Let's share our knowledge on Python Programming",
                        "id": "366190054572553",
                        "is_nsfw": null,
                        "metrics": {
                          "member_count": 763182
                        },
                        "moderators": [
                          {
                            "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/297738489_149183324449711_6655284279259187616_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx720x730&ctp=p64x64&_nc_cat=106&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc…",
                            "display_name": "Nusrat Jahan",
                            "id": "pfbid06GnASXZiYzDf35bsZJ3QLiKd5swrdR2gbc9txBtTEAZvJz1oW5bg7n1zMF1wzFJul",
                            "is_verified": null,
                            "url": "https://www.facebook.com/people/Nusrat-Jahan/pfbid06GnASXZiYzDf35bsZJ3QLiKd5swrdR2gbc9txBtTEAZvJz1oW5bg7n1zMF1wzFJul/",
                            "username": null
                          },
                          {
                            "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/242977119_109642788145497_5023972278328162431_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx1200x1200&ctp=s64x64&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_…",
                            "display_name": "Thesoftwarelion",
                            "id": "100079525026696",
                            "is_verified": null,
                            "url": "https://www.facebook.com/profile.php?id=100079525026696",
                            "username": null
                          },
                          {
                            "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/795255518_27959759933716428_4332290339331851799_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx1568x1556&ctp=s64x64&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED…",
                            "display_name": "Jamil Ahmed",
                            "id": "pfbid02tVzjeEoXMnLspija9MeZZfBPwsH4T5796pNLJhq8jhk2QZ8EThUdgbsDi7uPqFMXl",
                            "is_verified": null,
                            "url": "https://www.facebook.com/people/Jamil-Ahmed/pfbid02tVzjeEoXMnLspija9MeZZfBPwsH4T5796pNLJhq8jhk2QZ8EThUdgbsDi7uPqFMXl/",
                            "username": null
                          }
                        ],
                        "name": null,
                        "platform": "facebook",
                        "platform_specific": {
                          "facebook": {
                            "admin_count": 3,
                            "admin_ids": [
                              "pfbid06GnASXZiYzDf35bsZJ3QLiKd5swrdR2gbc9txBtTEAZvJz1oW5bg7n1zMF1wzFJul",
                              "100079525026696",
                              "pfbid02tVzjeEoXMnLspija9MeZZfBPwsH4T5796pNLJhq8jhk2QZ8EThUdgbsDi7uPqFMXl"
                            ],
                            "daily_post_count": 21,
                            "history_summary": "Group created on October 14, 2020. Name last changed on October 16, 2020.",
                            "is_visible": true,
                            "locations": [],
                            "moderator_count": 0,
                            "monthly_post_count": 1641,
                            "owner": null,
                            "weekly_new_member_count": null
                          }
                        },
                        "privacy": "public",
                        "rules": [
                          {
                            "description": "We're all in this together to create a welcoming environment. Let's treat everyone with respect. Healthy debates are natural, but kindness is required.",
                            "title": "Be Kind and Courteous"
                          },
                          {
                            "description": "Make sure everyone feels safe. Bullying of any kind isn't allowed, and degrading comments about things like race, religion, culture, sexual orientation, gender or identity will not be tolerated.",
                            "title": "No Hate Speech or Bullying"
                          },
                          {
                            "description": "Give more than you take to this group. Self-promotion, spam and irrelevant links aren't allowed.",
                            "title": "No Promotions or Spam"
                          }
                        ],
                        "title": "Python Programming",
                        "unknown_fields": [],
                        "url": "https://www.facebook.com/groups/366190054572553/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1564,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "community",
                          "id": "366190054572553",
                          "url": "https://www.facebook.com/groups/366190054572553/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookGroupResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Member count, rules, admins and activity",
        "tags": [
          "Facebook"
        ],
        "x-socialtap-endpoint": "facebook.group",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "community",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/group_posts": {
      "get": {
        "description": "Returns a public Facebook group's posts, a page at a time: newest first, most relevant, most recently active, or only its items for sale. Each post has its text with hashtags and mentions, photos, album, video or reel, link card or shared post, publish time, exact reaction, comment and share counts with the reactions by type, a video's views, and the member who posted it. Send the group's link, share link or ID.\n\nReturns `{data, page, meta}`: `data` holds up to 3 `Post` items (the shared schema, the same on every platform), Facebook's New posts: newest first by when a post entered the group's feed with sort=newest (the default), the group's items for sale, newest first by when each entered the group's feed with sort=listings, the posts most recently commented on or reacted to first with sort=recent_activity, Facebook's Most relevant ranking of the group's posts with sort=relevance. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/group_posts/ (Markdown: https://socialtap.dev/docs/reference/facebook/group_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/group_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/group_posts/"
        },
        "operationId": "facebook.group_posts.list",
        "parameters": [
          {
            "description": "The public group: its link (facebook.com/groups/<ID or name>, any tab of it, on any facebook.com host; the legacy group.php?gid=<ID>), its share link (facebook.com/share/g/<code>) or its bare numeric ID.",
            "example": "https://www.facebook.com/groups/366190054572553/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The public group: its link (facebook.com/groups/<ID or name>, any tab of it, on any facebook.com host; the legacy group.php?gid=<ID>), its share link (facebook.com/share/g/<code>) or its bare numeric ID.",
              "examples": [
                "https://www.facebook.com/groups/366190054572553/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. newest (default): the group's newest posts first (Facebook's New posts). relevance: Facebook's Most relevant ranking, the default of the group's page. recent_activity: the posts most recently commented on or reacted to first, however old (Facebook's Recent activity). listings: the group's items for sale only, newest first.",
            "example": "newest",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "newest",
              "description": "Order of the results. newest (default): the group's newest posts first (Facebook's New posts). relevance: Facebook's Most relevant ranking, the default of the group's page. recent_activity: the posts most recently commented on or reacted to first, however old (Facebook's Recent activity). listings: the group's items for sale only, newest first.",
              "enum": [
                "newest",
                "relevance",
                "recent_activity",
                "listings"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 3,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 3,
              "maximum": 3,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/657732699_4372938149635055_8298649324198958953_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx1920x1933&ctp=s80x80&_nc_cat=105&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&…",
                            "display_name": "Gift Glory Onuoha",
                            "id": "100007567395235",
                            "is_verified": false,
                            "url": "https://www.facebook.com/gift.glory.onuoha.2025",
                            "username": "gift.glory.onuoha.2025"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [
                            "Python",
                            "PythonProgramming",
                            "CodingChallenge"
                          ],
                          "id": "1837548820769995",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": "May be a graphic of text",
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1280,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.99422-6/888453030_1934834490835840_4759651598659241080_n.png?stp=dst-jpg_tt6&cstp=mx1024x1280&ctp=s1024x1280&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&…",
                              "width": 1024
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 0,
                            "like_count": 1,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": 1,
                            "view_count": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "feedback_id": "ZmVlZGJhY2s6cGZiaWQwSGZWelFmaURCb0xWU2J0Zjk0enlGeE5qN3VWaExUbTQ2ZHpSUjlnNTNTRjVCOG8ydWM2Z2dHTDU4ZTZmdEZMamw=",
                              "group": {
                                "id": "366190054572553",
                                "name": "Python Programming",
                                "url": "https://www.facebook.com/groups/366190054572553/"
                              },
                              "is_attachment_unavailable": false,
                              "link": null,
                              "listing": null,
                              "music": null,
                              "reactions": [
                                {
                                  "count": 1,
                                  "type": "like"
                                }
                              ],
                              "shared_post": null,
                              "video_id": null
                            }
                          },
                          "platform_type": "post",
                          "published_at": "2026-11-03T17:47:58Z",
                          "text": "DEVELOPER MYSTERIES #074 🕵️\n\nOne function changes a variable. Another function reads it.\n\nNeither function receives that variable as an argument.\n\nSo how do they stay connected?\n\nThis challenge tests your understanding of Python closures and variable scope.\n\nPredict the exact out…",
                          "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.99422-6/888453030_1934834490835840_4759651598659241080_n.png?stp=dst-jpg_tt6&cstp=mx1024x1280&ctp=s1024x1280&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/groups/366190054572553/posts/1837548820769995/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/795255518_27959759933716428_4332290339331851799_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx1568x1556&ctp=s80x80&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED…",
                            "display_name": "Jamil Ahmed",
                            "id": "pfbid02tVzjeEoXMnLspija9MeZZfBPwsH4T5796pNLJhq8jhk2QZ8EThUdgbsDi7uPqFMXl",
                            "is_verified": false,
                            "url": "https://www.facebook.com/people/Jamil-Ahmed/pfbid02tVzjeEoXMnLspija9MeZZfBPwsH4T5796pNLJhq8jhk2QZ8EThUdgbsDi7uPqFMXl/",
                            "username": null
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "1837472564110954",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": "May be a doodle of crowd",
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 616,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-6/886519251_28601992169493198_704461445392669909_n.jpg?stp=dst-jpg_tt6&cstp=mx2000x616&ctp=s2000x616&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_n…",
                              "width": 2000
                            }
                          ],
                          "mentions": [
                            "nurul.islam.971932",
                            "arwy.mhmd.552211",
                            "talha.qaimkhani.33"
                          ],
                          "metrics": {
                            "comment_count": 1,
                            "like_count": 0,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": 0,
                            "view_count": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "feedback_id": "ZmVlZGJhY2s6cGZiaWQwc3J5VXVYQ3pFaUFQYjVDZWRjbUF3TVlTQTZqQnlZVU1Rb1JIbksxTm9aYXlSUWRQRW0ydm5lTTE3OGVlZHB5Nmw=",
                              "group": {
                                "id": "366190054572553",
                                "name": "Python Programming",
                                "url": "https://www.facebook.com/groups/366190054572553/"
                              },
                              "is_attachment_unavailable": false,
                              "link": null,
                              "listing": null,
                              "music": null,
                              "reactions": [],
                              "shared_post": null,
                              "video_id": null
                            }
                          },
                          "platform_type": "post",
                          "published_at": "2026-11-03T16:12:44Z",
                          "text": "Let's welcome our new members!\nEmanuela Salomè,\nAdamu Abdullahi Adamu,\nNurul Islam,\nOlika Abdukerim Hassen,\nاروى محمد,\nMdAlamin Islam,\nAmos Dweh,\nElloy Neves,\nMuhammad Talha,\nAL IF,\nMaesha Jannat,\nLijalem Abera,\nMoosin Abdoo,\nTa Minh Tam,\nMorsalin Fahim,\n燈矢 轟,\nZayn Hosen,\nTasirul…",
                          "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-6/886519251_28601992169493198_704461445392669909_n.jpg?stp=dst-jpg_tt6&cstp=mx2000x616&ctp=s2000x616&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_n…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/groups/366190054572553/posts/1837472564110954/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/723111037_2124011641501346_211675270863137924_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx728x735&ctp=p80x80&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc…",
                            "display_name": "Sajid Hamid",
                            "id": "100016775924657",
                            "is_verified": false,
                            "url": "https://www.facebook.com/sajid.hamid.762469",
                            "username": "sajid.hamid.762469"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "1837467537444790",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": "May be an image of text",
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1620,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.99422-6/887924411_1161885399862305_7654919970390769521_n.png?stp=dst-jpg_tt6&cstp=mx1280x1920&ctp=s1080x2048&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&…",
                              "width": 1080
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 0,
                            "like_count": 0,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": 0,
                            "view_count": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "feedback_id": "ZmVlZGJhY2s6cGZiaWQwMnBrODFXZ1UzUlZCUmprZmg2S1F3bVFlUllTUFQ5OURXQVZQNlRuaTZNWnJqZzJYWUtKU1NMOXpiRVM2ZkhkNVJs",
                              "group": {
                                "id": "366190054572553",
                                "name": "Python Programming",
                                "url": "https://www.facebook.com/groups/366190054572553/"
                              },
                              "is_attachment_unavailable": false,
                              "link": null,
                              "listing": null,
                              "music": null,
                              "reactions": [],
                              "shared_post": null,
                              "video_id": null
                            }
                          },
                          "platform_type": "post",
                          "published_at": "2026-11-03T16:06:16Z",
                          "text": null,
                          "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.99422-6/887924411_1161885399862305_7654919970390769521_n.png?stp=dst-jpg_tt6&cstp=mx1280x1920&ctp=s1080x2048&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/groups/366190054572553/posts/1837467537444790/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1959,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "community",
                          "id": "366190054572553",
                          "url": "https://www.facebook.com/groups/366190054572553/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookGroup_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Public group posts with exact counts",
        "tags": [
          "Facebook"
        ],
        "x-socialtap-endpoint": "facebook.group_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Facebook's New posts: newest first by when a post entered the group's feed",
          "orders": {
            "listings": "the group's items for sale, newest first by when each entered the group's feed",
            "newest": "Facebook's New posts: newest first by when a post entered the group's feed",
            "recent_activity": "the posts most recently commented on or reacted to first",
            "relevance": "Facebook's Most relevant ranking of the group's posts"
          },
          "page_max": 3,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/listing": {
      "get": {
        "description": "Returns a public Facebook Marketplace listing from its link or ID: title, price, condition, description, photos and the seller with their rating. It also has the struck-through earlier price, currency, category, whether it's available, pending or sold, videos, the seller's join date, the area it's in with coordinates, and pickup, shipping or Buy now. Vehicles add make, model, trim, mileage, transmission and colors, and homes their details.\n\nReturns `{data, meta}`: `data` is a `Product` object (Facebook calls it a listing) (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/listing/ (Markdown: https://socialtap.dev/docs/reference/facebook/listing/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/listing/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/listing/"
        },
        "operationId": "facebook.listing.get",
        "parameters": [
          {
            "description": "Facebook Marketplace listing URL (/marketplace/item/<id>, also under a city's or category's path, or the older /commerce/listing/<id>; www., m. and web. hosts, any query string), or the listing's numeric ID.",
            "example": "https://www.facebook.com/marketplace/item/1456476040872340/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Facebook Marketplace listing URL (/marketplace/item/<id>, also under a city's or category's path, or the older /commerce/listing/<id>; www., m. and web. hosts, any query string), or the listing's numeric ID.",
              "examples": [
                "https://www.facebook.com/marketplace/item/1456476040872340/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "platform_specific.facebook.latitude",
                          "platform_specific.facebook.longitude"
                        ],
                        "attributes": [
                          {
                            "name": "Condition",
                            "value": "Used - like new"
                          },
                          {
                            "name": "Material",
                            "value": "Steel"
                          },
                          {
                            "name": "Bicycle Type",
                            "value": "Cruiser Bike"
                          }
                        ],
                        "availability": "in_stock",
                        "category": "Bicycles",
                        "category_id": "1658310421102081",
                        "condition": "used",
                        "condition_label": "Used - like new",
                        "country_code": null,
                        "currency": "USD",
                        "description": "Barely used, 24\" steel Huffy Bike perfect for outdoor terrain and everyday rides \n\n-Fully functional brakestyle with progressive sizing and clean seat cover \n\n-If needed, I am willing to deliver the bike to your home or flexible for an at-home pick-up",
                        "id": "1456476040872340",
                        "max_price": 45,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": null,
                            "expires_at": "2026-10-25T18:00:00Z",
                            "height": 720,
                            "thumbnail_url": null,
                            "type": "image",
                            "url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.84726-6/796968328_2328210001329072_7831806606744114668_n.jpg?stp=dst-jpg_p720x720_tt6&_nc_cat=101&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBE…",
                            "width": 960
                          },
                          {
                            "alt_text": null,
                            "duration_ms": null,
                            "expires_at": "2026-10-25T18:00:00Z",
                            "height": 960,
                            "thumbnail_url": null,
                            "type": "image",
                            "url": "https://scontent-atl3-1.xx.fbcdn.net/v/t45.5328-4/800796705_2129037657962264_2251174291161391522_n.jpg?stp=dst-jpg_p720x720_tt6&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED…",
                            "width": 720
                          }
                        ],
                        "original_price": null,
                        "platform": "facebook",
                        "platform_specific": {
                          "facebook": {
                            "delivery_types": [
                              "in_person",
                              "door_pickup",
                              "door_dropoff"
                            ],
                            "is_buy_now_enabled": false,
                            "is_local_pickup": true,
                            "latitude": 40.663146972656,
                            "location": "Rockville Centre, NY",
                            "location_id": null,
                            "longitude": -73.635864257812,
                            "postal_code": null,
                            "price_period": null,
                            "published_at": "2026-09-09T13:45:37Z",
                            "seller_joined_at": "2026-09-09T13:20:08Z",
                            "seller_rating": null,
                            "seller_rating_count": null
                          }
                        },
                        "price": 45,
                        "seller": {
                          "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/795438461_122093964159482116_3880964857956452102_n.jpg?stp=c334.0.1380.1380a_cp6_dst-jpg_tt6&cstp=mx1380x1380&ctp=s100x100&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-…",
                          "display_name": "Meredith Hall",
                          "id": "pfbid0bhJ8iBQwR4XVDCyEgQU4hKBvHyZPUVgJuBYVSa4henf9QvFwHycKvjgyYX3imnYCl",
                          "is_verified": false,
                          "url": null,
                          "username": null
                        },
                        "shipping": {
                          "fee": null,
                          "is_offered": false
                        },
                        "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.84726-6/796968328_2328210001329072_7831806606744114668_n.jpg?stp=dst-jpg_p720x720_tt6&_nc_cat=101&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBE…",
                        "title": "Barely Used, \"26 Turquoise Huffy Bike",
                        "type": "listing",
                        "unknown_fields": [],
                        "url": "https://www.facebook.com/marketplace/item/1456476040872340/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 2624,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "product",
                          "id": "1456476040872340",
                          "url": "https://www.facebook.com/marketplace/item/1456476040872340/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookListingResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Item for sale with price, photos and seller",
        "tags": [
          "Facebook Marketplace"
        ],
        "x-socialtap-endpoint": "facebook.listing",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "product",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/photos": {
      "get": {
        "description": "Returns the photos on a public Facebook Page's or person's Photos tab, newest first, a page at a time: its own uploads or the photos it's tagged in. Each photo has its ID and link, its full-size image with width, height and link expiry, the square crop the grid shows, and Facebook's description of what it pictures. Send a name, ID or link, and an optional time window Facebook applies itself.\n\nReturns `{data, page, meta}`: `data` holds up to 8 `Post` items (the shared schema, the same on every platform), Newest first, as the Photos tab shows them. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/photos/ (Markdown: https://socialtap.dev/docs/reference/facebook/photos/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/photos/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/photos/"
        },
        "operationId": "facebook.photos.list",
        "parameters": [
          {
            "description": "The Facebook profile (a Page's or a person's): its vanity name (NASA, case-insensitive), its numeric profile ID, or any link to it: facebook.com/<name> with any tab after it, profile.php?id=…, /people/<name>/<id>, /p/<name>-<id>.",
            "example": "NASA",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Facebook profile (a Page's or a person's): its vanity name (NASA, case-insensitive), its numeric profile ID, or any link to it: facebook.com/<name> with any tab after it, profile.php?id=…, /people/<name>/<id>, /p/<name>-<id>.",
              "examples": [
                "NASA"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Which photos: uploaded, the profile's own (the tab Facebook calls <name>'s Photos); tagged, the ones others tagged it in (Photos of <name>), which people's profiles have and Pages don't: an empty list when the profile shows none.",
            "example": "",
            "in": "query",
            "name": "tab",
            "schema": {
              "default": "uploaded",
              "description": "Which photos: uploaded, the profile's own (the tab Facebook calls <name>'s Photos); tagged, the ones others tagged it in (Photos of <name>), which people's profiles have and Pages don't: an empty list when the profile shows none.",
              "enum": [
                "uploaded",
                "tagged"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only photos created at or after this time: Facebook's own filter, since a photo in this list carries no date.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only photos created at or after this time: Facebook's own filter, since a photo in this list carries no date.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Only photos created before this time: Facebook's own filter, so the first page starts there.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Only photos created before this time: Facebook's own filter, so the first page starts there.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 8,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 8,
              "maximum": 8,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/243095782_416661036495945_3843362260429099279_n.png?stp=dst-png_s100x100&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&edm=SCRUBBED&_nc_gid=SCRUBBED&oh=SCRUBBED&oe=F2…",
                            "display_name": "NASA - National Aeronautics and Space Administration",
                            "id": "100044561550831",
                            "is_verified": true,
                            "url": "https://www.facebook.com/NASA",
                            "username": "NASA"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "1675983760563660",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": "An intricate cloud of white dust takes center stage in this photo, rising in a windy pillar. The background features rust-colored dust with dots of distant stars and galaxies shining through.",
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1385,
                              "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/871223884_1487536193225483_3660942795677810580_n.png?stp=c308.0.1385.1385a_dst-jpg_tt6&cstp=mx1385x1385&ctp=s552x414&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc…",
                              "type": "image",
                              "url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/871223884_1487536193225483_3660942795677810580_n.png?stp=dst-jpg_tt6&cstp=mx2000x1385&ctp=s2000x1385&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_n…",
                              "width": 2000
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "feedback_id": null,
                              "group": null,
                              "is_attachment_unavailable": null,
                              "link": null,
                              "listing": null,
                              "music": null,
                              "reactions": [],
                              "shared_post": null,
                              "video_id": null
                            }
                          },
                          "platform_type": "photo",
                          "published_at": null,
                          "text": null,
                          "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/871223884_1487536193225483_3660942795677810580_n.png?stp=c308.0.1385.1385a_dst-jpg_tt6&cstp=mx1385x1385&ctp=s552x414&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [
                            "coauthors",
                            "hashtags",
                            "mentions"
                          ],
                          "url": "https://www.facebook.com/photo/?fbid=1675983760563660"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/243095782_416661036495945_3843362260429099279_n.png?stp=dst-png_s100x100&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&edm=SCRUBBED&_nc_gid=SCRUBBED&oh=SCRUBBED&oe=F2…",
                            "display_name": "NASA - National Aeronautics and Space Administration",
                            "id": "100044561550831",
                            "is_verified": true,
                            "url": "https://www.facebook.com/NASA",
                            "username": "NASA"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "1675279167300786",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": "An image that shows the \"MAX POWER Kennedy Space Center\" app as it appears in the iOS App Store.",
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1294,
                              "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/864280748_2020097565352172_6759494451320615303_n.png?stp=c377.0.1294.1294a_dst-jpg_tt6&cstp=mx1294x1294&ctp=s552x414&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_…",
                              "type": "image",
                              "url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/864280748_2020097565352172_6759494451320615303_n.png?stp=dst-jpg_tt6&cstp=mx2048x1294&ctp=s2048x1294&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&…",
                              "width": 2048
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "feedback_id": null,
                              "group": null,
                              "is_attachment_unavailable": null,
                              "link": null,
                              "listing": null,
                              "music": null,
                              "reactions": [],
                              "shared_post": null,
                              "video_id": null
                            }
                          },
                          "platform_type": "photo",
                          "published_at": null,
                          "text": null,
                          "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/864280748_2020097565352172_6759494451320615303_n.png?stp=c377.0.1294.1294a_dst-jpg_tt6&cstp=mx1294x1294&ctp=s552x414&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [
                            "coauthors",
                            "hashtags",
                            "mentions"
                          ],
                          "url": "https://www.facebook.com/photo/?fbid=1675279167300786"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/243095782_416661036495945_3843362260429099279_n.png?stp=dst-png_s100x100&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&edm=SCRUBBED&_nc_gid=SCRUBBED&oh=SCRUBBED&oe=F2…",
                            "display_name": "NASA - National Aeronautics and Space Administration",
                            "id": "100044561550831",
                            "is_verified": true,
                            "url": "https://www.facebook.com/NASA",
                            "username": "NASA"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "1672152994280070",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": "Three jet aircraft, each with a white nose and blue body, fly in a triangle formation against a clear blue sky. White trails follow each jet.",
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1280,
                              "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/872064392_1772088687399080_6520374397283068537_n.png?stp=c320.0.1280.1280a_dst-jpg_tt6&cstp=mx1280x1280&ctp=s552x414&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_…",
                              "type": "image",
                              "url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/872064392_1772088687399080_6520374397283068537_n.png?stp=dst-jpg_tt6&cstp=mx1920x1280&ctp=s1920x1280&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&…",
                              "width": 1920
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "feedback_id": null,
                              "group": null,
                              "is_attachment_unavailable": null,
                              "link": null,
                              "listing": null,
                              "music": null,
                              "reactions": [],
                              "shared_post": null,
                              "video_id": null
                            }
                          },
                          "platform_type": "photo",
                          "published_at": null,
                          "text": null,
                          "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/872064392_1772088687399080_6520374397283068537_n.png?stp=c320.0.1280.1280a_dst-jpg_tt6&cstp=mx1280x1280&ctp=s552x414&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [
                            "coauthors",
                            "hashtags",
                            "mentions"
                          ],
                          "url": "https://www.facebook.com/photo/?fbid=1672152994280070"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 829,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "100044561550831",
                          "url": "https://www.facebook.com/nasa"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookPhotosResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Full-size photos, uploaded or tagged",
        "tags": [
          "Facebook"
        ],
        "x-socialtap-endpoint": "facebook.photos",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Newest first, as the Photos tab shows them",
          "page_max": 8,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/place_events": {
      "get": {
        "description": "Returns the public Facebook events in a city from its events link or ID, for every coming date or a window such as this weekend. Each event has its name, whether it's scheduled, under way or over, its start time with its offset from UTC, whether it's online, its venue and city, cover, ticket price label, the series a recurring date belongs to, the group it was created in, and how many people are going and interested.\n\nReturns `{data, page, meta}`: `data` holds up to 12 `Event` items (the shared schema, the same on every platform), Facebook's ranking of the city's events, not by date. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Facebook's words: `metrics.attendee_count` is going.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/place_events/ (Markdown: https://socialtap.dev/docs/reference/facebook/place_events/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/place_events/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/place_events/"
        },
        "operationId": "facebook.place_events.list",
        "parameters": [
          {
            "description": "The city: its Facebook events link (facebook.com/events/explore/<city>/<id>/, with a time window after it such as /today/; m. and web. hosts too) or its numeric ID. Facebook keys a city by this ID: the Facebook Marketplace Location Search API answers it from a city's name, as id, and the Facebook Event API as platform_specific.facebook.city_id; in the /pages/<name>/<id> link of its place.url, the ID is the number at the end.",
            "example": "https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The city: its Facebook events link (facebook.com/events/explore/<city>/<id>/, with a time window after it such as /today/; m. and web. hosts too) or its numeric ID. Facebook keys a city by this ID: the Facebook Marketplace Location Search API answers it from a city's name, as id, and the Facebook Event API as platform_specific.facebook.city_id; in the /pages/<name>/<id> link of its place.url, the ID is the number at the end.",
              "examples": [
                "https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only events in this window, as Facebook's city page filters them; every coming event when omitted. Overrides a window in the link.",
            "example": "this_weekend",
            "in": "query",
            "name": "time",
            "schema": {
              "description": "Only events in this window, as Facebook's city page filters them; every coming event when omitted. Overrides a window in the link.",
              "enum": [
                "today",
                "tomorrow",
                "this_weekend",
                "this_week",
                "next_week"
              ],
              "examples": [
                "this_weekend"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 12,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 12,
              "maximum": 12,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "platform_specific.facebook.metrics.interested_count"
                          ],
                          "categories": [],
                          "community_id": null,
                          "cover_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-6/691737832_122221920272546827_3621567388430112740_n.jpg?stp=c0.45.1600.764a_dst-jpg_tt6&cstp=mx1600x764&ctp=s640x640&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.xx&_n…",
                          "description": null,
                          "end_at": null,
                          "hosts": [],
                          "id": "1009766568177406",
                          "is_online": false,
                          "metrics": {
                            "attendee_count": 253
                          },
                          "name": "90s Day Party: St. Petersburg, FL 💿",
                          "parent_id": null,
                          "place": {
                            "address": null,
                            "city": "Saint Petersburg, Florida",
                            "country_code": null,
                            "id": null,
                            "latitude": null,
                            "longitude": null,
                            "name": "2655 6th Ave S, St Petersburg, FL 33712-1653, United States",
                            "url": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "city_id": "111326725552547",
                              "date_text": "Sat, Nov 7 at 3:00 PM EST",
                              "frequency": null,
                              "metrics": {
                                "interested_count": 7500,
                                "response_count": null
                              },
                              "occurrence_count": null,
                              "price_text": null,
                              "ticket_provider": null
                            }
                          },
                          "start_at": "2026-11-07T20:00:00Z",
                          "status": "scheduled",
                          "ticket_url": null,
                          "time_zone": null,
                          "unknown_fields": [
                            "hosts",
                            "categories"
                          ],
                          "url": "https://www.facebook.com/events/1009766568177406/",
                          "utc_offset_minutes": -300
                        },
                        {
                          "approximate_fields": [],
                          "categories": [],
                          "community_id": null,
                          "cover_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-6/876819554_1438940761722368_3293008712652972469_n.jpg?stp=c0.29.1920.917a_dst-jpg_tt6&cstp=mx1920x917&ctp=s640x640&_nc_cat=102&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.xx&_nc_…",
                          "description": null,
                          "end_at": null,
                          "hosts": [],
                          "id": "1117858504340275",
                          "is_online": false,
                          "metrics": {
                            "attendee_count": 4
                          },
                          "name": "The Rocky Horror Spanksgiving Show!",
                          "parent_id": null,
                          "place": {
                            "address": null,
                            "city": "Saint Petersburg, Florida",
                            "country_code": null,
                            "id": "113001216940331",
                            "latitude": null,
                            "longitude": null,
                            "name": "Green Light: Cinema, Lounge, Kitchen",
                            "url": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "city_id": "111326725552547",
                              "date_text": "Sat, Nov 14 at 8:30 PM EST",
                              "frequency": null,
                              "metrics": {
                                "interested_count": 79,
                                "response_count": null
                              },
                              "occurrence_count": null,
                              "price_text": null,
                              "ticket_provider": null
                            }
                          },
                          "start_at": "2026-11-15T01:30:00Z",
                          "status": "scheduled",
                          "ticket_url": null,
                          "time_zone": null,
                          "unknown_fields": [
                            "hosts",
                            "categories"
                          ],
                          "url": "https://www.facebook.com/events/1117858504340275/",
                          "utc_offset_minutes": -300
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.facebook.metrics.interested_count"
                          ],
                          "categories": [],
                          "community_id": null,
                          "cover_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.99422-6/851378089_1425164076476687_7376004806964005311_n.png?stp=c0.186.1080.516a_dst-jpg_tt6&cstp=mx1080x516&ctp=s640x640&_nc_cat=108&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc…",
                          "description": null,
                          "end_at": null,
                          "hosts": [],
                          "id": "1488319459545073",
                          "is_online": false,
                          "metrics": {
                            "attendee_count": 107
                          },
                          "name": "St. Pete Yoga Fest",
                          "parent_id": null,
                          "place": {
                            "address": null,
                            "city": "Saint Petersburg, Florida",
                            "country_code": null,
                            "id": null,
                            "latitude": null,
                            "longitude": null,
                            "name": "The St. Pete Pier",
                            "url": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "city_id": "111326725552547",
                              "date_text": "Sat, Nov 7 at 9:00 AM EST",
                              "frequency": null,
                              "metrics": {
                                "interested_count": 1100,
                                "response_count": null
                              },
                              "occurrence_count": null,
                              "price_text": null,
                              "ticket_provider": null
                            }
                          },
                          "start_at": "2026-11-07T14:00:00Z",
                          "status": "scheduled",
                          "ticket_url": null,
                          "time_zone": null,
                          "unknown_fields": [
                            "hosts",
                            "categories"
                          ],
                          "url": "https://www.facebook.com/events/1488319459545073/",
                          "utc_offset_minutes": -300
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 793,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "place",
                          "id": "111326725552547",
                          "url": "https://www.facebook.com/events/explore/-/111326725552547/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookPlace_eventsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "By date window, with going and interested counts",
        "tags": [
          "Facebook Events"
        ],
        "x-socialtap-endpoint": "facebook.place_events",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 10800,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Facebook's ranking of the city's events, not by date",
          "page_max": 12,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "event",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/post": {
      "get": {
        "description": "Returns a public Facebook post, photo, video or reel from its link or ID: text, author, date, and exact reaction, comment, share and view counts. It also has the reactions by type, hashtags and mentions, every photo of an album, the video file with its thumbnail, size and length, and the shared link card or reshared post.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/post/ (Markdown: https://socialtap.dev/docs/reference/facebook/post/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/post/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/post/"
        },
        "operationId": "facebook.post.get",
        "parameters": [
          {
            "description": "Facebook post, photo, video or reel URL: /<page>/posts/<id>, permalink.php and story.php links, /photo/?fbid= and /<page>/photos/… links, reel, watch, video.php and /<page>/videos/… links, fb.watch and /share/p|v|r/ share links (m., mbasic. and web. hosts too), or a numeric post, photo or video ID.",
            "example": "https://www.facebook.com/reel/4075684206061398/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Facebook post, photo, video or reel URL: /<page>/posts/<id>, permalink.php and story.php links, /photo/?fbid= and /<page>/photos/… links, reel, watch, video.php and /<page>/videos/… links, fb.watch and /share/p|v|r/ share links (m., mbasic. and web. hosts too), or a numeric post, photo or video ID.",
              "examples": [
                "https://www.facebook.com/reel/4075684206061398/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/243095782_416661036495945_3843362260429099279_n.png?stp=cp0_dst-png&cstp=mx800x800&ctp=s80x80&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b…",
                          "display_name": "NASA - National Aeronautics and Space Administration",
                          "id": "100044561550831",
                          "is_verified": true,
                          "url": "https://www.facebook.com/NASA",
                          "username": "NASA"
                        },
                        "coauthors": [],
                        "duration_ms": 39381,
                        "hashtags": [],
                        "id": "1670768087751894",
                        "is_nsfw": null,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": null,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": 39381,
                            "expires_at": "2026-10-25T18:00:00Z",
                            "height": 2160,
                            "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t15.5256-10/877658791_1832631854542515_4430770165954872904_n.jpg?stp=dst-jpg_tt6&cstp=mx1920x1080&ctp=s960x960&_nc_cat=101&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_n…",
                            "type": "video",
                            "url": "https://video-atl3-1.xx.fbcdn.net/o1/v/t2/f2/m366/AQMS1Kmor5hpvEHAtxe3lVPcxOt4prhHPFgKMLcPxvBSvELFTPbkpMPfDvKx8gg5c4VOCCZrgCV0tzqv9ahLzz1s3O0N2Cdf2DaUFGeUSO0WTA.mp4?_nc_cat=106&_nc_sid=SCRUBBED&_nc_ht=video-atl3-1.xx.fbcdn.net&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=SCRUBBE…",
                            "width": 3840
                          }
                        ],
                        "mentions": [
                          "CanadianSpaceAgency",
                          "ISS"
                        ],
                        "metrics": {
                          "comment_count": 55,
                          "like_count": 574,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": null,
                          "share_count": null,
                          "view_count": 52713
                        },
                        "platform": "facebook",
                        "platform_specific": {
                          "facebook": {
                            "feedback_id": "ZmVlZGJhY2s6MTY3MDc2ODA4Nzc1MTg5NA==",
                            "group": null,
                            "is_attachment_unavailable": null,
                            "link": null,
                            "listing": null,
                            "music": null,
                            "reactions": [
                              {
                                "count": 476,
                                "type": "like"
                              },
                              {
                                "count": 70,
                                "type": "love"
                              },
                              {
                                "count": 13,
                                "type": "care"
                              }
                            ],
                            "shared_post": null,
                            "video_id": "4075684206061398"
                          }
                        },
                        "platform_type": "reel",
                        "published_at": "2026-10-29T11:48:37Z",
                        "text": "NASA astronaut Anil Menon and Canadian Space Agency astronaut Joshua Kutryk are getting ready to head out of the International Space Station!\n \nAt this point, they have donned spacesuits called Extravehicular Mobility Units (EMUs), which contain all the protections and life suppo…",
                        "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t15.5256-10/877658791_1832631854542515_4430770165954872904_n.jpg?stp=dst-jpg_tt6&cstp=mx1920x1080&ctp=s960x960&_nc_cat=101&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_n…",
                        "title": null,
                        "type": "video",
                        "unknown_fields": [],
                        "url": "https://www.facebook.com/reel/4075684206061398/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1353,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "1670768087751894",
                          "url": "https://www.facebook.com/reel/4075684206061398/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookPostResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Post, photo, video or reel with exact counts",
        "tags": [
          "Facebook"
        ],
        "x-socialtap-endpoint": "facebook.post",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/posts": {
      "get": {
        "description": "Returns a public Facebook Page's or person's posts, newest first, a page at a time, from its name, ID or link. Each post has its text with hashtags and mentions, its photos, album, video or reel, its link card or the post it shares, its publish time, and exact reaction, comment and share counts with the reactions by type, plus a video's views and the author's name, picture and badge. since and until set a time window Facebook applies itself.\n\nReturns `{data, page, meta}`: `data` holds up to 3 `Post` items (the shared schema, the same on every platform), newest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/posts/ (Markdown: https://socialtap.dev/docs/reference/facebook/posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/posts/"
        },
        "operationId": "facebook.posts.list",
        "parameters": [
          {
            "description": "The Facebook profile (a Page's or a person's): its vanity name (NASA, case-insensitive), its numeric profile ID, or any link to it: facebook.com/<name> with any tab after it, profile.php?id=…, /people/<name>/<id>, /p/<name>-<id>.",
            "example": "NASA",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Facebook profile (a Page's or a person's): its vanity name (NASA, case-insensitive), its numeric profile ID, or any link to it: facebook.com/<name> with any tab after it, profile.php?id=…, /people/<name>/<id>, /p/<name>-<id>.",
              "examples": [
                "NASA"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only posts published at or after this time. Facebook filters the timeline itself, and the walk ends at the first older post.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only posts published at or after this time. Facebook filters the timeline itself, and the walk ends at the first older post.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Only posts published before this time: Facebook's own filter, so the first page starts there.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Only posts published before this time: Facebook's own filter, so the first page starts there.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 3,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 3,
              "maximum": 3,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/243095782_416661036495945_3843362260429099279_n.png?stp=cp0_dst-png&cstp=mx800x800&ctp=s80x80&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b…",
                            "display_name": "NASA - National Aeronautics and Space Administration",
                            "id": "100044561550831",
                            "is_verified": true,
                            "url": "https://www.facebook.com/NASA",
                            "username": "NASA"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "1676179567210746",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 3,
                            "like_count": 64,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": 1,
                            "view_count": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "feedback_id": "ZmVlZGJhY2s6cGZiaWQwMmlSQkFpeENQd1R1Zml6aUFWTXZRdWEzTEJuZHk2dGYzUHl2NDE1UWtaZjdGdjdneTM1U2VpRVltN3Z0UGNMcGps",
                              "group": null,
                              "is_attachment_unavailable": false,
                              "link": null,
                              "listing": null,
                              "music": null,
                              "reactions": [
                                {
                                  "count": 60,
                                  "type": "like"
                                },
                                {
                                  "count": 2,
                                  "type": "love"
                                },
                                {
                                  "count": 1,
                                  "type": "care"
                                }
                              ],
                              "shared_post": {
                                "author": {
                                  "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/516872204_1189959146491994_4245240435554141606_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx2048x2047&ctp=s80x80&_nc_cat=103&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&…",
                                  "display_name": "Learn With NASA",
                                  "id": "100064337605401",
                                  "is_verified": true,
                                  "url": "https://www.facebook.com/LearnWithNASA",
                                  "username": "LearnWithNASA"
                                },
                                "id": "1615866537234584",
                                "url": "https://www.facebook.com/LearnWithNASA/posts/pfbid0qRf3ZGacva8hj6xVFVrBA29EF3mMnZGmcG6zYUaeLRB1yHARL2KHoPFaqH5jM72yl"
                              },
                              "video_id": null
                            }
                          },
                          "platform_type": "post",
                          "published_at": "2026-11-03T19:27:52Z",
                          "text": null,
                          "thumbnail_url": null,
                          "title": null,
                          "type": "text",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/NASA/posts/pfbid02iRBAixCPwTufiziAVMvQua3LBndy6tf3Pyv415QkZf7Fv7gy35SeiEYm7vtPcLpjl"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/243095782_416661036495945_3843362260429099279_n.png?stp=cp0_dst-png&cstp=mx800x800&ctp=s80x80&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b…",
                            "display_name": "NASA - National Aeronautics and Space Administration",
                            "id": "100044561550831",
                            "is_verified": true,
                            "url": "https://www.facebook.com/NASA",
                            "username": "NASA"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "1675983783896991",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": "An intricate cloud of white dust takes center stage in this photo, rising in a windy pillar. The background features rust-colored dust with dots of distant stars and galaxies shining through.",
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1385,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/871223884_1487536193225483_3660942795677810580_n.png?stp=dst-jpg_tt6&cstp=mx2000x1385&ctp=s2000x1385&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_n…",
                              "width": 2000
                            }
                          ],
                          "mentions": [
                            "NASAWebb"
                          ],
                          "metrics": {
                            "comment_count": 58,
                            "like_count": 2431,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": 185,
                            "view_count": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "feedback_id": "ZmVlZGJhY2s6cGZiaWQwZDJ3bUtXZm9Lc1Q5d0s5bndvV1c1SHpzRWd2MjhjSno5UTZuUDVBMjZCTGNrdVFlQWJCWnNQM0RuSm1pU2s3Q2w=",
                              "group": null,
                              "is_attachment_unavailable": false,
                              "link": null,
                              "listing": null,
                              "music": null,
                              "reactions": [
                                {
                                  "count": 1657,
                                  "type": "like"
                                },
                                {
                                  "count": 687,
                                  "type": "love"
                                },
                                {
                                  "count": 42,
                                  "type": "care"
                                }
                              ],
                              "shared_post": null,
                              "video_id": null
                            }
                          },
                          "platform_type": "post",
                          "published_at": "2026-11-03T15:00:35Z",
                          "text": "Pspsps 🐈‍⬛\n\nThis smoky specter is the Cat’s Head Nebula, captured in intricate detail by NASA's James Webb Space Telescope. Its name comes from its shape, which resembles a cosmic kitty sitting with its back toward the viewer. What do you see?",
                          "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/871223884_1487536193225483_3660942795677810580_n.png?stp=dst-jpg_tt6&cstp=mx2000x1385&ctp=s2000x1385&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_n…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/NASA/posts/pfbid0d2wmKWfoKsT9wK9nwoWW5HzsEgv28cJz9Q6nP5A26BLckuQeAbBZsP3DnJmiSk7Cl"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/243095782_416661036495945_3843362260429099279_n.png?stp=cp0_dst-png&cstp=mx800x800&ctp=s80x80&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b…",
                            "display_name": "NASA - National Aeronautics and Space Administration",
                            "id": "100044561550831",
                            "is_verified": true,
                            "url": "https://www.facebook.com/NASA",
                            "username": "NASA"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "1675279183967451",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": "An image that shows the \"MAX POWER Kennedy Space Center\" app as it appears in the iOS App Store.",
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1294,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/864280748_2020097565352172_6759494451320615303_n.png?stp=dst-jpg_tt6&cstp=mx2048x1294&ctp=s2048x1294&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&…",
                              "width": 2048
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 18,
                            "like_count": 248,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": 29,
                            "view_count": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "feedback_id": "ZmVlZGJhY2s6cGZiaWQwMnBqYUxiZmhBbkZtckRvb254eDdHeWVwVDFIN3BGYmk5d3JwcXF1TDZvTTVnVFVKYmZCRTJCVDJYY2h0RzkzcjJs",
                              "group": null,
                              "is_attachment_unavailable": false,
                              "link": null,
                              "listing": null,
                              "music": null,
                              "reactions": [
                                {
                                  "count": 215,
                                  "type": "like"
                                },
                                {
                                  "count": 25,
                                  "type": "love"
                                },
                                {
                                  "count": 5,
                                  "type": "care"
                                }
                              ],
                              "shared_post": null,
                              "video_id": null
                            }
                          },
                          "platform_type": "post",
                          "published_at": "2026-11-02T22:30:00Z",
                          "text": "Planning your trip to MAX POWER? We've got a tool for that.\n\nEvent schedules, maps, and FAQs are at your fingertips with the MAX POWER app. It's free and available to download from official app stores on iOS and Android devices: https://go.nasa.gov/3V2iiWX",
                          "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.99422-6/864280748_2020097565352172_6759494451320615303_n.png?stp=dst-jpg_tt6&cstp=mx2048x1294&ctp=s2048x1294&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/NASA/posts/pfbid02pjaLbfhAnFmrDoonxx7GyepT1H7pFbi9wrpqquL6oM5gTUJbfBE2BT2XchtG93r2l"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1578,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "100044561550831",
                          "url": "https://www.facebook.com/nasa"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookPostsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Newest first, with exact reactions and shares",
        "tags": [
          "Facebook"
        ],
        "x-socialtap-endpoint": "facebook.posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "page_max": 3,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/profile": {
      "get": {
        "description": "Returns a public Facebook Page's or person's profile from its name, ID or link: name, bio, category, picture, links and exact follower count. It also has the cover, verified badge, following count and creation date. A business adds its address, phone, email, rating, reviews, price range, services and weekly opening hours. A Page adds whether it is running ads, its Ad Library Page ID, its confirmed owner, where its admins are and its past names. A person adds the work, education and places their intro shows.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/profile/ (Markdown: https://socialtap.dev/docs/reference/facebook/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/profile/"
        },
        "operationId": "facebook.profile.get",
        "parameters": [
          {
            "description": "The Facebook profile (a Page's or a person's): its vanity name (NASA, case-insensitive), its numeric profile ID or Page ID, or any link to it: facebook.com/<name> with any tab after it, profile.php?id=…, /people/<name>/<id>, /p/<name>-<id>, /pages/category/…, fb.me/<name>.",
            "example": "NASA",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Facebook profile (a Page's or a person's): its vanity name (NASA, case-insensitive), its numeric profile ID or Page ID, or any link to it: facebook.com/<name> with any tab after it, profile.php?id=…, /people/<name>/<id>, /p/<name>-<id>, /pages/category/…, fb.me/<name>.",
              "examples": [
                "NASA"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/243095782_416661036495945_3843362260429099279_n.png?stp=dst-png&cstp=mx800x800&ctp=s800x800&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b28…",
                        "banner_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.99422-6/809146614_4484013928506139_3181913787670602881_n.png?stp=dst-jpg_tt6&cstp=mx2047x1487&ctp=s2047x1487&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&…",
                        "bio": "Explore the universe and discover our home planet. \nThere's space for everybody. ✨",
                        "category": "Government organization",
                        "country_code": null,
                        "created_at": "2009-03-04T21:45:25Z",
                        "display_name": "NASA - National Aeronautics and Space Administration",
                        "external_links": [
                          {
                            "title": "nasa.gov/nasa-app",
                            "url": "https://www.nasa.gov/nasa-app/"
                          },
                          {
                            "title": "nasa.gov",
                            "url": "https://www.nasa.gov/"
                          }
                        ],
                        "id": "100044561550831",
                        "is_private": null,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 28731903,
                          "following_count": 52,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "facebook",
                        "platform_specific": {
                          "facebook": {
                            "ad_library_entity_type": null,
                            "admin_countries": [
                              {
                                "count": 15,
                                "country": "United States"
                              }
                            ],
                            "alternate_name": null,
                            "business_hours": [],
                            "education": [],
                            "email": "public-inquiries@hq.nasa.gov",
                            "gender": null,
                            "hometown": null,
                            "hours_status": null,
                            "instagram_follower_count": null,
                            "instagram_username": null,
                            "is_deleted": null,
                            "is_instagram_verified": null,
                            "is_memorialized": false,
                            "is_political_advertiser": false,
                            "is_running_ads": false,
                            "name_changes": [
                              {
                                "changed_at": "2014-04-07T19:49:21Z",
                                "name": "NASA - National Aeronautics and Space Administration"
                              }
                            ],
                            "owner_location": "WASHINGTON DC, 20024 United States of America",
                            "owner_name": "NATIONAL AERONAUTICS AND SPACE ADMINISTRATION",
                            "page_id": "54971236771",
                            "phone": null,
                            "price_range": null,
                            "rating": null,
                            "recommend_percent": null,
                            "relationship": null,
                            "review_count": null,
                            "services": [],
                            "talking_about_count": null,
                            "were_here_count": null,
                            "work": []
                          }
                        },
                        "type": "organization",
                        "unknown_fields": [],
                        "url": "https://www.facebook.com/NASA",
                        "username": "NASA"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1393,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "100044561550831",
                          "url": "https://www.facebook.com/NASA"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact follower count, contact info and hours",
        "tags": [
          "Facebook"
        ],
        "x-socialtap-endpoint": "facebook.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/reels": {
      "get": {
        "description": "Returns a public Facebook Page's or person's latest reels, newest first, a page at a time, from its Reels tab. Each reel has its caption with hashtags and mentions, video file with length and size, cover image, publish time, views, reactions, comments and shares, the sound it credits, its paid-partnership label, and its author and co-authors. Send a name, ID or link, and an optional time window.\n\nReturns `{data, page, meta}`: `data` holds up to 10 `Post` items (the shared schema, the same on every platform), newest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/reels/ (Markdown: https://socialtap.dev/docs/reference/facebook/reels/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/reels/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/reels/"
        },
        "operationId": "facebook.reels.list",
        "parameters": [
          {
            "description": "The Facebook profile (a Page's or a person's): its vanity name (natgeo, case-insensitive), its numeric profile ID, or any link to it: facebook.com/<name> with any tab after it, profile.php?id=…, /people/<name>/<id>, /p/<name>-<id>.",
            "example": "natgeo",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Facebook profile (a Page's or a person's): its vanity name (natgeo, case-insensitive), its numeric profile ID, or any link to it: facebook.com/<name> with any tab after it, profile.php?id=…, /people/<name>/<id>, /p/<name>-<id>.",
              "examples": [
                "natgeo"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only reels published at or after this time. The walk ends at the first older reel.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only reels published at or after this time. The walk ends at the first older reel.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Only reels published before this time. The walk starts at the newest and pages until it gets there, as far as the list goes logged out.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Only reels published before this time. The walk starts at the newest and pages until it gets there, as far as the list goes logged out.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 10,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 10,
              "maximum": 10,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "metrics.view_count"
                          ],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/475979419_1182307929933302_8257114326919725462_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx400x400&ctp=s80x80&_nc_cat=101&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_n…",
                            "display_name": "National Geographic",
                            "id": "100044623170418",
                            "is_verified": true,
                            "url": "https://www.facebook.com/natgeo",
                            "username": "natgeo"
                          },
                          "coauthors": [],
                          "duration_ms": 10965,
                          "hashtags": [
                            "BestOfTheWorld"
                          ],
                          "id": "1710773677086722",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 10965,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t15.5256-10/884618825_30181052474816111_4627007225022417326_n.jpg?stp=dst-jpg_tt6&cstp=mx1080x1920&ctp=s960x960&_nc_cat=102&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_…",
                              "type": "video",
                              "url": "https://video-atl3-1.xx.fbcdn.net/o1/v/t2/f2/m366/AQNrV380hk7S-DTuHqiJuH0duqmGAV4F5h0pFX8Y1jzD_a9iu6MXjdSYaqruMbo4oweLTk3bOQwbcZLqDNlodHI05oDrnmF6tD5ebX_u7tp9YQ.mp4?_nc_cat=108&_nc_sid=SCRUBBED&_nc_ht=video-atl3-1.xx.fbcdn.net&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=SCRUBBE…",
                              "width": 1080
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 7,
                            "like_count": 262,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": 6,
                            "view_count": 20000
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "feedback_id": "ZmVlZGJhY2s6cGZiaWQwdTR5aWlmZGRBR1hHZnVpS29yRmVpVGo1NEJlZkpxZGFiQ0ptelM3NzNKUko1UHdmOE1mcjFXc0tIVWFMOFNKaGw=",
                              "group": null,
                              "is_attachment_unavailable": null,
                              "link": null,
                              "listing": null,
                              "music": null,
                              "reactions": [],
                              "shared_post": null,
                              "video_id": "1631236835362063"
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-11-03T22:10:02Z",
                          "text": "Cascading more than 2,500 feet (762 meters), Gocta waterfall, near the village of Cocachimba in northern Peru, is one of the world’s tallest waterfalls. It's just one of the incredible sights that visitors can discover in northern Peru, a region gaining further interest thanks to…",
                          "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t15.5256-10/884618825_30181052474816111_4627007225022417326_n.jpg?stp=dst-jpg_tt6&cstp=mx1080x1920&ctp=s960x960&_nc_cat=102&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "platform_specific.facebook.reactions"
                          ],
                          "url": "https://www.facebook.com/reel/1631236835362063/"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count"
                          ],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/475979419_1182307929933302_8257114326919725462_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx400x400&ctp=s80x80&_nc_cat=101&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_n…",
                            "display_name": "National Geographic",
                            "id": "100044623170418",
                            "is_verified": true,
                            "url": "https://www.facebook.com/natgeo",
                            "username": "natgeo"
                          },
                          "coauthors": [],
                          "duration_ms": 32085,
                          "hashtags": [
                            "BestOfTheWorld"
                          ],
                          "id": "1709576883873068",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 32085,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t15.5256-10/886300512_29290661380565589_5039700284158011991_n.jpg?stp=dst-jpg_tt6&cstp=mx1080x1920&ctp=s960x960&_nc_cat=107&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_…",
                              "type": "video",
                              "url": "https://video-atl3-2.xx.fbcdn.net/o1/v/t2/f2/m366/AQMRYjf0DimPSWb5O4bvII4BWep8VM0GY9JergDwo_v7skKMWJyX4oGxwcjqSKqoKTVOw22I4p-nPKxCi2eM3_i6OM8Nbzr0q_-iGIozc3hkJQ.mp4?_nc_cat=102&_nc_sid=SCRUBBED&_nc_ht=video-atl3-2.xx.fbcdn.net&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=SCRUBBE…",
                              "width": 1080
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 11,
                            "like_count": 1353,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": 48,
                            "view_count": 182000
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "feedback_id": "ZmVlZGJhY2s6cGZiaWQwNG1KVXBDMkV2aVJIc0pVVkYxQWVWVU5WY0FoaTJtN1JoNHRuTUw1TnUyV2RxYlloRE5NYXM4eG9HaTdiN2ZXeWw=",
                              "group": null,
                              "is_attachment_unavailable": null,
                              "link": null,
                              "listing": null,
                              "music": null,
                              "reactions": [],
                              "shared_post": null,
                              "video_id": "29290659273899133"
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-11-02T18:00:14Z",
                          "text": "Chase waterfalls in Cocachimba, wander the ancient walls of Kuélap, explore the streets of Chachapoyas, and venture deep into Quiocta's caverns. Northern Peru is full of places that stay with you long after you've left.\n\nCurated by Nat Geo’s team of experts and editors around the…",
                          "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t15.5256-10/886300512_29290661380565589_5039700284158011991_n.jpg?stp=dst-jpg_tt6&cstp=mx1080x1920&ctp=s960x960&_nc_cat=107&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "platform_specific.facebook.reactions"
                          ],
                          "url": "https://www.facebook.com/reel/29290659273899133/"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count"
                          ],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/475979419_1182307929933302_8257114326919725462_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx400x400&ctp=s80x80&_nc_cat=101&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_n…",
                            "display_name": "National Geographic",
                            "id": "100044623170418",
                            "is_verified": true,
                            "url": "https://www.facebook.com/natgeo",
                            "username": "natgeo"
                          },
                          "coauthors": [],
                          "duration_ms": 90920,
                          "hashtags": [
                            "DrainTheOceans"
                          ],
                          "id": "1708712703959486",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 90920,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t15.5256-10/883629753_4647701772175040_9209268733401403077_n.jpg?stp=dst-jpg_tt6&cstp=mx405x720&ctp=s405x720&_nc_cat=108&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_…",
                              "type": "video",
                              "url": "https://video-atl3-1.xx.fbcdn.net/o1/v/t2/f2/m366/AQMNqdBI936nFPwhn9KByEaD3NFWV-NUvAIKm-M1EuyRRvLTVW8QSn00axkLwpgsnt96nuvurTD_6A3i60nsQu34MUTmXoiSttQSLeeF80_kBQ.mp4?_nc_cat=106&_nc_sid=SCRUBBED&_nc_ht=video-atl3-1.xx.fbcdn.net&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=SCRUBBE…",
                              "width": 1080
                            }
                          ],
                          "mentions": [
                            "DisneyPlus",
                            "hulu"
                          ],
                          "metrics": {
                            "comment_count": 20,
                            "like_count": 1957,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": 67,
                            "view_count": 234000
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "feedback_id": "ZmVlZGJhY2s6cGZiaWQwMmlOMVRCcWZxQlB3YnRQaVdrTXpFUXhLVnJuV2Z2Z0NTWGRjbWEzTnNCNTNQVENIb3AyNHROdmNqaWo5dUNOYmFs",
                              "group": null,
                              "is_attachment_unavailable": null,
                              "link": null,
                              "listing": null,
                              "music": null,
                              "reactions": [],
                              "shared_post": null,
                              "video_id": "1888471619202224"
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-11-01T22:00:00Z",
                          "text": "Using ancient dinosaur bones and skin, experts were able to piece together the identity of this mysterious fossil. \n\n#DrainTheOceans is now streaming on Disney+ and Hulu.",
                          "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t15.5256-10/883629753_4647701772175040_9209268733401403077_n.jpg?stp=dst-jpg_tt6&cstp=mx405x720&ctp=s405x720&_nc_cat=108&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "platform_specific.facebook.reactions"
                          ],
                          "url": "https://www.facebook.com/reel/1888471619202224/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1880,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "100044623170418",
                          "url": "https://www.facebook.com/natgeo"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookReelsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Newest first, with views and video files",
        "tags": [
          "Facebook"
        ],
        "x-socialtap-endpoint": "facebook.reels",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "page_max": 10,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/replies": {
      "get": {
        "description": "Returns the replies to one comment on a public Facebook post, photo, video or reel, oldest first, replies to replies included. Each reply has its text, time, permalink, the comment it answers, exact reaction count with the reactions by type, attached photo and whether the post's author wrote it, and the replier's ID, name, profile link, picture and verified badge. Send the comment's link from the Facebook Comments API, or the post's link and the comment's ID.\n\nReturns `{data, page, meta}`: `data` holds up to 10 `Comment` items (the shared schema, the same on every platform), oldest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/replies/ (Markdown: https://socialtap.dev/docs/reference/facebook/replies/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/replies/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/replies/"
        },
        "operationId": "facebook.replies.list",
        "parameters": [
          {
            "description": "The comment's link, as the Facebook Comments API returns it in data[].url: the post, photo, video or reel link with ?comment_id= (a reply's link, with reply_comment_id too, reads the thread it is in). Or any link the Facebook Comments API takes (post, permalink.php, story.php, photo, reel, watch, video, fb.watch and share links, m., mbasic. and web. hosts, a numeric ID) with the comment_id param.",
            "example": "https://www.facebook.com/cnn/posts/pfbid034UhZgwWAxAbbbqcVT6TLJQz9aGu17AWYtaZib2nUzN6ueQKyvyoBSJ1Ao4R7Aibzl",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The comment's link, as the Facebook Comments API returns it in data[].url: the post, photo, video or reel link with ?comment_id= (a reply's link, with reply_comment_id too, reads the thread it is in). Or any link the Facebook Comments API takes (post, permalink.php, story.php, photo, reel, watch, video, fb.watch and share links, m., mbasic. and web. hosts, a numeric ID) with the comment_id param.",
              "examples": [
                "https://www.facebook.com/cnn/posts/pfbid034UhZgwWAxAbbbqcVT6TLJQz9aGu17AWYtaZib2nUzN6ueQKyvyoBSJ1Ao4R7Aibzl?comment_id=1134072982431001"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "ID of the top-level comment whose replies to list (data[].id from the Facebook Comments API). Required unless url is a comment's link.",
            "example": "2241840356745830",
            "in": "query",
            "name": "comment_id",
            "schema": {
              "description": "ID of the top-level comment whose replies to list (data[].id from the Facebook Comments API). Required unless url is a comment's link.",
              "examples": [
                "1134072982431001"
              ],
              "maxLength": 25,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 10,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 10,
              "maximum": 10,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/468351006_10159593503532255_6774442294622346739_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx488x488&ctp=s32x32&_nc_cat=104&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_…",
                            "display_name": "Joe Krozel",
                            "id": "pfbid02adNe4WrmH1JqGH4w8KfHniEngAHQXky7jRYawTwtdhGRAdoBdb1kRtdzy6iNRJbBl",
                            "is_verified": false,
                            "url": "https://www.facebook.com/joe.krozel",
                            "username": "joe.krozel"
                          },
                          "edited_at": null,
                          "id": "2219135261976665",
                          "is_by_post_author": null,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 1,
                            "reply_count": 1
                          },
                          "parent_id": "2241840356745830",
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "author_gender": "male",
                              "image_url": null,
                              "reactions": [
                                {
                                  "count": 1,
                                  "type": "haha"
                                }
                              ]
                            }
                          },
                          "post_id": "1515533333772646",
                          "published_at": "2026-10-29T22:42:30Z",
                          "text": "Steve Jenkins Hey loser, Republicans don't take polls, so the polls underreport their support.  Fox is just passing it on as it is received.  Blue wave is fictitious.",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/cnn/posts/pfbid034UhZgwWAxAbbbqcVT6TLJQz9aGu17AWYtaZib2nUzN6ueQKyvyoBSJ1Ao4R7Aibzl?comment_id=2241840356745830&reply_comment_id=2219135261976665"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/453750901_122190017804061302_7467119486547392352_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx849x850&ctp=s32x32&_nc_cat=101&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&…",
                            "display_name": "Jenna Redstone",
                            "id": "61551839077397",
                            "is_verified": false,
                            "url": "https://www.facebook.com/marion.weiler.2023",
                            "username": "marion.weiler.2023"
                          },
                          "edited_at": null,
                          "id": "1995314554488520",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 1,
                            "reply_count": 2
                          },
                          "parent_id": "2241840356745830",
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "author_gender": "female",
                              "image_url": null,
                              "reactions": [
                                {
                                  "count": 1,
                                  "type": "haha"
                                }
                              ]
                            }
                          },
                          "post_id": "1515533333772646",
                          "published_at": "2026-10-30T08:40:18Z",
                          "text": "Steve Jenkins They always have been more truthful.",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/cnn/posts/pfbid034UhZgwWAxAbbbqcVT6TLJQz9aGu17AWYtaZib2nUzN6ueQKyvyoBSJ1Ao4R7Aibzl?comment_id=2241840356745830&reply_comment_id=1995314554488520"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/511906991_24085412141097078_6841766951798215929_n.jpg?stp=cp0_dst-jpg_tt6&cstp=mx648x648&ctp=s32x32&_nc_cat=107&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_…",
                            "display_name": "Steve Jenkins",
                            "id": "pfbid02tWsPGdCcwsR9MDGBfyqw45aVVh34i1ZxbmHZ41TniRyXx4VMoQAmgt2ikBy1fTLql",
                            "is_verified": false,
                            "url": "https://www.facebook.com/people/Steve-Jenkins/pfbid02tWsPGdCcwsR9MDGBfyqw45aVVh34i1ZxbmHZ41TniRyXx4VMoQAmgt2ikBy1fTLql/",
                            "username": null
                          },
                          "edited_at": null,
                          "id": "1118282917795771",
                          "is_by_post_author": null,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 0,
                            "reply_count": 0
                          },
                          "parent_id": "1995314554488520",
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "author_gender": "male",
                              "image_url": null,
                              "reactions": []
                            }
                          },
                          "post_id": "1515533333772646",
                          "published_at": "2026-10-30T13:00:28Z",
                          "text": "Jenna Redstone Right, that's why they had to pay out 700+ million dollars for lying, you Maga cultists are funny as hell..",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/cnn/posts/pfbid034UhZgwWAxAbbbqcVT6TLJQz9aGu17AWYtaZib2nUzN6ueQKyvyoBSJ1Ao4R7Aibzl?comment_id=2241840356745830&reply_comment_id=1118282917795771"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1166,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "1515533333772646",
                          "url": "https://www.facebook.com/cnn/posts/pfbid034UhZgwWAxAbbbqcVT6TLJQz9aGu17AWYtaZib2nUzN6ueQKyvyoBSJ1Ao4R7Aibzl"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "end"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookRepliesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Thread under a comment, both levels",
        "tags": [
          "Facebook"
        ],
        "x-socialtap-endpoint": "facebook.replies",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "oldest first",
          "page_max": 10,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/search_ads": {
      "get": {
        "description": "Searches Meta's public Ad Library by keyword and returns the matching ads from Facebook, Instagram, Messenger, Threads and the Audience Network. Each ad has its advertiser, the days it first and last ran, whether it's still active, where it ran and its creatives: headline, text, link, call to action, images and videos. Political and social-issue ads add the payer and Meta's impression, reach and spend ranges. Filter by country, language, status and dates. Ads come most impressions first, the Ad Library's own order.\n\nReturns `{data, page, meta}`: `data` holds up to 10 `Ad` items (the shared schema, the same on every platform), most impressions first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/search_ads/ (Markdown: https://socialtap.dev/docs/reference/facebook/search_ads/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/search_ads/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/search_ads/"
        },
        "operationId": "facebook.search_ads.list",
        "parameters": [
          {
            "description": "Keywords matched against the ad's text, in any order. Wrap the query in double quotes (\"cold brew\") to match an exact phrase.",
            "example": "coffee",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Keywords matched against the ad's text, in any order. Wrap the query in double quotes (\"cold brew\") to match an exact phrase.",
              "examples": [
                "coffee"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only ads delivered in this country. All countries when omitted.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only ads delivered in this country. All countries when omitted.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). Only ads whose text Meta detects as this language (the primary subtag counts: pt-BR searches pt). All languages when omitted.",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). Only ads whose text Meta detects as this language (the primary subtag counts: pt-BR searches pt). All languages when omitted.",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items that are still running (active), only items that stopped (inactive), or both (all). Default: all.",
            "example": "active",
            "in": "query",
            "name": "status",
            "schema": {
              "default": "all",
              "description": "Only items that are still running (active), only items that stopped (inactive), or both (all). Default: all.",
              "enum": [
                "active",
                "inactive",
                "all"
              ],
              "examples": [
                "active"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Ads count when they ran during the window: an ad that last ran (last_shown_at) before since is left out; active ads ran until today.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Ads count when they ran during the window: an ad that last ran (last_shown_at) before since is left out; active ads ran until today.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Ads count when they ran during the window: an ad that first ran (first_shown_at) at or after until is left out.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Ads count when they ran during the window: an ad that first ran (first_shown_at) at or after until is left out.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 10,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 10,
              "maximum": 10,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "advertiser": {
                            "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.35426-6/739782028_1533198008291919_1079542453788497101_n.jpg?stp=dst-jpg_s60x60_tt6&_nc_cat=104&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&…",
                            "display_name": "American Health Support Community",
                            "id": "966175593248497",
                            "is_verified": null,
                            "url": "https://www.facebook.com/profile.php?id=61588018263996",
                            "username": null
                          },
                          "approximate_fields": [
                            "first_shown_at"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": "My aunt called me a creep for putting a camera in Nana’s living room.\n\nNana called me practical.\n\nThen the camera caught something worse than a fall.\n\nI need to be clear about one thing before anyone decides what kind of grandson I am.\n\nNana asked for the camera.\n\nNot me.\n\nNot my…",
                              "cta_text": "Learn more",
                              "link_description": null,
                              "link_url": "https://shop.pipitea.com/hbt/kd/sp-nm",
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": null,
                                  "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/742001725_2100792434176297_9060645049521596104_n.jpg?stp=dst-jpg_s600x600_tt6&_nc_cat=100&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBE…",
                                  "type": "image",
                                  "url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/742501415_1706621370582971_4085631001896338504_n.jpg?_nc_cat=103&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&oe=F2A52380",
                                  "width": null
                                }
                              ],
                              "title": "Natural Relief in Weeks"
                            }
                          ],
                          "first_shown_at": "2026-07-18T07:00:00Z",
                          "id": "2619351891814847",
                          "impressions": null,
                          "is_active": true,
                          "is_political": false,
                          "languages": [],
                          "last_shown_at": null,
                          "paid_by": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "advertiser_categories": [
                                "Community Center"
                              ],
                              "advertiser_instagram": null,
                              "advertiser_instagram_follower_count": null,
                              "advertiser_like_count": 4072,
                              "beneficiary": null,
                              "collation_count": 1,
                              "collation_id": "2362783507580471",
                              "cta_type": "learn_more",
                              "impression_shares": null,
                              "is_advertiser_deleted": false,
                              "is_removed": null,
                              "is_synthetic": false,
                              "link_caption": "shop.pipitea.com",
                              "partner": null,
                              "removal_reasons": [],
                              "special_ad_categories": [],
                              "targeting": []
                            }
                          },
                          "publisher_platforms": [
                            "facebook",
                            "instagram",
                            "audience_network"
                          ],
                          "reach": null,
                          "spend": null,
                          "type": "image",
                          "unknown_fields": [
                            "country_codes",
                            "languages",
                            "platform_specific.facebook.removal_reasons"
                          ],
                          "url": "https://www.facebook.com/ads/library/?id=2619351891814847"
                        },
                        {
                          "advertiser": {
                            "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/712623693_1599994994434095_1320701223312676781_n.jpg?stp=dst-jpg_s60x60_tt6&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&…",
                            "display_name": "American Health Support Community",
                            "id": "966175593248497",
                            "is_verified": null,
                            "url": "https://www.facebook.com/profile.php?id=61588018263996",
                            "username": null
                          },
                          "approximate_fields": [
                            "first_shown_at",
                            "last_shown_at"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": "I almost looked past the woman who saved my husband's life. She was seventy-nine, sitting alone at the booth next to ours at the Cracker Barrel off Highway 31. A glass of milk in front of her. She kept stirring it. She wasn't eating.\n\nIf I'd known, the night I leaned over and ask…",
                              "cta_text": "Learn more",
                              "link_description": "\"I've tried everything to support my kidney function naturally. Fish oil, CoQ10, cutting protein, stressing about every meal. Nothing moved the needle enough to satisfy my doctor. Hibiscus tea is the first thing that actually showed up in my numbers. It's been 3 months and my eGF…",
                              "link_url": "https://shop.pipitea.com/hbt/kd/sp",
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": null,
                                  "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.35426-6/711729685_1717035472767079_186136568392095276_n.jpg?stp=dst-jpg_s600x600_tt6&_nc_cat=104&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED…",
                                  "type": "image",
                                  "url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/713729791_868879862958547_7409366389733397444_n.jpg?_nc_cat=107&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&oe=F2A52380",
                                  "width": null
                                }
                              ],
                              "title": "Natural Relief in Weeks"
                            }
                          ],
                          "first_shown_at": "2026-06-01T07:00:00Z",
                          "id": "1923645134954720",
                          "impressions": null,
                          "is_active": false,
                          "is_political": false,
                          "languages": [],
                          "last_shown_at": "2026-10-30T07:00:00Z",
                          "paid_by": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "advertiser_categories": [
                                "Community Center"
                              ],
                              "advertiser_instagram": null,
                              "advertiser_instagram_follower_count": null,
                              "advertiser_like_count": 4072,
                              "beneficiary": null,
                              "collation_count": 1,
                              "collation_id": "1304791095118481",
                              "cta_type": "learn_more",
                              "impression_shares": null,
                              "is_advertiser_deleted": false,
                              "is_removed": null,
                              "is_synthetic": false,
                              "link_caption": "shop.pipitea.com",
                              "partner": null,
                              "removal_reasons": [],
                              "special_ad_categories": [],
                              "targeting": []
                            }
                          },
                          "publisher_platforms": [
                            "facebook",
                            "instagram",
                            "audience_network"
                          ],
                          "reach": null,
                          "spend": null,
                          "type": "image",
                          "unknown_fields": [
                            "country_codes",
                            "languages",
                            "platform_specific.facebook.removal_reasons"
                          ],
                          "url": "https://www.facebook.com/ads/library/?id=1923645134954720"
                        },
                        {
                          "advertiser": {
                            "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/712025330_1303417705276292_736671271727941526_n.jpg?stp=dst-jpg_s60x60_tt6&_nc_cat=103&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&o…",
                            "display_name": "American Health Support Community",
                            "id": "966175593248497",
                            "is_verified": null,
                            "url": "https://www.facebook.com/profile.php?id=61588018263996",
                            "username": null
                          },
                          "approximate_fields": [
                            "first_shown_at",
                            "last_shown_at"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": "I almost looked past the woman who saved my husband's life. She was seventy-nine, sitting alone at the booth next to ours at the Cracker Barrel off Highway 31. A glass of milk in front of her. She kept stirring it. She wasn't eating.\n\nIf I'd known, the night I leaned over and ask…",
                              "cta_text": "Learn more",
                              "link_description": "\"I've tried everything to support my kidney function naturally. Fish oil, CoQ10, cutting protein, stressing about every meal. Nothing moved the needle enough to satisfy my doctor. Hibiscus tea is the first thing that actually showed up in my numbers. It's been 3 months and my eGF…",
                              "link_url": "https://shop.pipitea.com/hbt/kd/sp",
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": null,
                                  "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.35426-6/711737708_4485707625086258_2353150069319301753_n.jpg?stp=dst-jpg_s600x600_tt6&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBE…",
                                  "type": "image",
                                  "url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.35426-6/710755472_911440771966686_1736050619245168045_n.jpg?_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&oe=F2A52380",
                                  "width": null
                                }
                              ],
                              "title": "Natural Relief in Weeks"
                            }
                          ],
                          "first_shown_at": "2026-06-01T07:00:00Z",
                          "id": "2140497416496021",
                          "impressions": null,
                          "is_active": false,
                          "is_political": false,
                          "languages": [],
                          "last_shown_at": "2026-10-30T07:00:00Z",
                          "paid_by": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "advertiser_categories": [
                                "Community Center"
                              ],
                              "advertiser_instagram": null,
                              "advertiser_instagram_follower_count": null,
                              "advertiser_like_count": 4072,
                              "beneficiary": null,
                              "collation_count": 1,
                              "collation_id": "884617784669236",
                              "cta_type": "learn_more",
                              "impression_shares": null,
                              "is_advertiser_deleted": false,
                              "is_removed": null,
                              "is_synthetic": false,
                              "link_caption": "shop.pipitea.com",
                              "partner": null,
                              "removal_reasons": [],
                              "special_ad_categories": [],
                              "targeting": []
                            }
                          },
                          "publisher_platforms": [
                            "facebook",
                            "instagram",
                            "audience_network"
                          ],
                          "reach": null,
                          "spend": null,
                          "type": "image",
                          "unknown_fields": [
                            "country_codes",
                            "languages",
                            "platform_specific.facebook.removal_reasons"
                          ],
                          "url": "https://www.facebook.com/ads/library/?id=2140497416496021"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1482,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookSearch_adsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Ads by keyword, with creatives and run dates",
        "tags": [
          "Facebook Ad Library"
        ],
        "x-socialtap-endpoint": "facebook.search_ads",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "most impressions first",
          "page_max": 10,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "ad",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/search_advertisers": {
      "get": {
        "description": "Returns the advertisers in Meta's public Ad Library that match a name, username or Page ID, as its search box suggests them. Each has its Page ID (the ID its ads are filed under), name, username, picture, category, country, verified badge and exact follower count, plus the Instagram account Meta links to it with that account's exact followers and badge. Send a country to rank the matches for it.\n\nReturns `{data, page, meta}`: `data` holds up to 15 `Profile` items (Facebook calls it a advertiser) (the shared schema, the same on every platform), the search box's own order. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/search_advertisers/ (Markdown: https://socialtap.dev/docs/reference/facebook/search_advertisers/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/search_advertisers/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/search_advertisers/"
        },
        "operationId": "facebook.search_advertisers.list",
        "parameters": [
          {
            "description": "An advertiser's name or part of it, its Facebook username or its Page ID (never its profile ID), as typed into the Ad Library's search box, in any language (baileys, コカ・コーラ, 20531316728).",
            "example": "baileys",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "An advertiser's name or part of it, its Facebook username or its Page ID (never its profile ID), as typed into the Ad Library's search box, in any language (baileys, コカ・コーラ, 20531316728).",
              "examples": [
                "baileys"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The country to search from: Meta ranks the matches for it, and an advertiser from elsewhere can still appear. An ISO 3166-1 alpha-2 code such as US. Every country when omitted.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The country to search from: Meta ranks the matches for it, and an advertiser from elsewhere can still appear. An ISO 3166-1 alpha-2 code such as US. Every country when omitted.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 15,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 15,
              "maximum": 15,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/443711959_876169351217288_8358221437311147045_n.jpg?stp=dst-jpg_s200x200_tt6&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED…",
                          "banner_url": null,
                          "bio": null,
                          "category": "Wine/spirits",
                          "country_code": null,
                          "created_at": null,
                          "display_name": "Baileys",
                          "external_links": [],
                          "id": "73939360594",
                          "is_private": null,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": 4664402,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "ad_library_entity_type": "PERSON_PROFILE",
                              "admin_countries": [],
                              "alternate_name": null,
                              "business_hours": [],
                              "education": [],
                              "email": null,
                              "gender": null,
                              "hometown": null,
                              "hours_status": null,
                              "instagram_follower_count": 248872,
                              "instagram_username": "baileysofficial",
                              "is_deleted": false,
                              "is_instagram_verified": true,
                              "is_memorialized": null,
                              "is_political_advertiser": null,
                              "is_running_ads": null,
                              "name_changes": [],
                              "owner_location": null,
                              "owner_name": null,
                              "page_id": "73939360594",
                              "phone": null,
                              "price_range": null,
                              "rating": null,
                              "recommend_percent": null,
                              "relationship": null,
                              "review_count": null,
                              "services": [],
                              "talking_about_count": null,
                              "were_here_count": null,
                              "work": []
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.facebook.services",
                            "platform_specific.facebook.business_hours"
                          ],
                          "url": "https://www.facebook.com/Baileys",
                          "username": "Baileys"
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.30808-1/445756898_874337388053755_8139191371735594555_n.jpg?stp=dst-jpg_s200x200_tt6&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED…",
                          "banner_url": null,
                          "bio": null,
                          "category": "Wine/spirits",
                          "country_code": "GB",
                          "created_at": null,
                          "display_name": "Baileys",
                          "external_links": [],
                          "id": "151277918233754",
                          "is_private": null,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": 4664402,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "ad_library_entity_type": "PERSON_PROFILE",
                              "admin_countries": [],
                              "alternate_name": null,
                              "business_hours": [],
                              "education": [],
                              "email": null,
                              "gender": null,
                              "hometown": null,
                              "hours_status": null,
                              "instagram_follower_count": null,
                              "instagram_username": null,
                              "is_deleted": false,
                              "is_instagram_verified": null,
                              "is_memorialized": null,
                              "is_political_advertiser": null,
                              "is_running_ads": null,
                              "name_changes": [],
                              "owner_location": null,
                              "owner_name": null,
                              "page_id": "151277918233754",
                              "phone": null,
                              "price_range": null,
                              "rating": null,
                              "recommend_percent": null,
                              "relationship": null,
                              "review_count": null,
                              "services": [],
                              "talking_about_count": null,
                              "were_here_count": null,
                              "work": []
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.facebook.services",
                            "platform_specific.facebook.business_hours"
                          ],
                          "url": "https://www.facebook.com/BaileysGB",
                          "username": "BaileysGB"
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-1/884884889_1163136826368298_466053757919124974_n.avif?stp=dst-avif_s200x200&_nc_cat=104&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b289&oh=SCRUBBED&o…",
                          "banner_url": null,
                          "bio": null,
                          "category": "Wine/spirits",
                          "country_code": "US",
                          "created_at": null,
                          "display_name": "Baileys",
                          "external_links": [],
                          "id": "109408419132021",
                          "is_private": null,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": 4664402,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "ad_library_entity_type": "PERSON_PROFILE",
                              "admin_countries": [],
                              "alternate_name": null,
                              "business_hours": [],
                              "education": [],
                              "email": null,
                              "gender": null,
                              "hometown": null,
                              "hours_status": null,
                              "instagram_follower_count": 149344,
                              "instagram_username": "baileysus",
                              "is_deleted": false,
                              "is_instagram_verified": true,
                              "is_memorialized": null,
                              "is_political_advertiser": null,
                              "is_running_ads": null,
                              "name_changes": [],
                              "owner_location": null,
                              "owner_name": null,
                              "page_id": "109408419132021",
                              "phone": null,
                              "price_range": null,
                              "rating": null,
                              "recommend_percent": null,
                              "relationship": null,
                              "review_count": null,
                              "services": [],
                              "talking_about_count": null,
                              "were_here_count": null,
                              "work": []
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.facebook.services",
                            "platform_specific.facebook.business_hours"
                          ],
                          "url": "https://www.facebook.com/baileysus",
                          "username": "baileysus"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 434,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookSearch_advertisersResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Advertisers by name, with Page IDs",
        "tags": [
          "Facebook Ad Library"
        ],
        "x-socialtap-endpoint": "facebook.search_advertisers",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search box's own order",
          "page_max": 15,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/search_events": {
      "get": {
        "description": "Searches public Facebook events by keyword, anywhere or in one place, and returns them in Facebook's own ranking. Each result has the event's ID, link and name, its start, venue and cover, whether it's online, its status, and how many people are interested and going. Narrow by date with since and until. When Facebook refuses the query, results come from the search's page and are thin: mostly the ID, link, name and a picture.\n\nReturns `{data, page, meta}`: `data` holds up to 20 `Event` items (the shared schema, the same on every platform), Facebook's ranking of the results, not by date. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Facebook's words: `metrics.attendee_count` is going.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/search_events/ (Markdown: https://socialtap.dev/docs/reference/facebook/search_events/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/search_events/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/search_events/"
        },
        "operationId": "facebook.search_events.list",
        "parameters": [
          {
            "description": "The words to search events for, as in Facebook's event search: names, artists, topics, places.",
            "example": "jazz",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "The words to search events for, as in Facebook's event search: names, artists, topics, places.",
              "examples": [
                "jazz"
              ],
              "maxLength": 500,
              "type": "string"
            }
          },
          {
            "description": "Only events in this place: its Facebook events link (facebook.com/events/explore/<city>/<id>/) or its numeric ID, the one the Facebook Marketplace Location Search API answers as id and the Facebook City Events API takes. Omitted, Facebook searches everywhere.",
            "example": "108424279189115",
            "in": "query",
            "name": "location",
            "schema": {
              "description": "Only events in this place: its Facebook events link (facebook.com/events/explore/<city>/<id>/) or its numeric ID, the one the Facebook Marketplace Location Search API answers as id and the Facebook City Events API takes. Omitted, Facebook searches everywhere.",
              "examples": [
                "108424279189115"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 20,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "categories": [],
                          "community_id": null,
                          "cover_url": "https://scontent.ftol2-1.fna.fbcdn.net/v/t39.30808-6/737325123_4499264600219134_9055237808772320460_n.jpg?stp=c0.138.1254.836a_dst-jpg_tt6&cstp=mx1254x836&ctp=s1254x836&_nc_cat=101&_nc_map=urlgen_bucketless&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&…",
                          "description": null,
                          "end_at": null,
                          "hosts": [],
                          "id": "935939818906345",
                          "is_online": false,
                          "metrics": {
                            "attendee_count": 1
                          },
                          "name": "JAZZ fest «Blue Note»",
                          "parent_id": null,
                          "place": {
                            "address": null,
                            "city": null,
                            "country_code": null,
                            "id": null,
                            "latitude": null,
                            "longitude": null,
                            "name": "Тверская Область",
                            "url": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "city_id": null,
                              "date_text": "Tue, Jun 1, 2027 - Jun 15, 2027",
                              "frequency": null,
                              "metrics": {
                                "interested_count": 3,
                                "response_count": null
                              },
                              "occurrence_count": null,
                              "price_text": null,
                              "ticket_provider": null
                            }
                          },
                          "start_at": "2027-05-31T21:00:00Z",
                          "status": "scheduled",
                          "ticket_url": null,
                          "time_zone": null,
                          "unknown_fields": [
                            "hosts",
                            "categories"
                          ],
                          "url": "https://www.facebook.com/events/935939818906345/",
                          "utc_offset_minutes": null
                        },
                        {
                          "approximate_fields": [],
                          "categories": [],
                          "community_id": null,
                          "cover_url": "https://scontent.ftol2-1.fna.fbcdn.net/v/t39.30808-6/583712862_1185733750330218_7695504167411277837_n.jpg?stp=c160.0.1728.1152a_dst-jpg_tt6&cstp=mx1728x1152&ctp=s1728x1152&_nc_cat=106&_nc_map=urlgen_bucketless&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                          "description": null,
                          "end_at": null,
                          "hosts": [],
                          "id": "733095653165588",
                          "is_online": false,
                          "metrics": {
                            "attendee_count": null
                          },
                          "name": "Jazz Jam",
                          "parent_id": null,
                          "place": {
                            "address": null,
                            "city": null,
                            "country_code": null,
                            "id": "602685513168965",
                            "latitude": null,
                            "longitude": null,
                            "name": "Funk 'n Waffles Syracuse",
                            "url": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "city_id": null,
                              "date_text": "Sun, Nov 8 at 3:00 PM EST and 7 more",
                              "frequency": null,
                              "metrics": {
                                "interested_count": 403,
                                "response_count": null
                              },
                              "occurrence_count": null,
                              "price_text": null,
                              "ticket_provider": null
                            }
                          },
                          "start_at": "2025-11-23T20:00:00Z",
                          "status": "ongoing",
                          "ticket_url": null,
                          "time_zone": null,
                          "unknown_fields": [
                            "hosts",
                            "categories"
                          ],
                          "url": "https://www.facebook.com/events/733095653165588/",
                          "utc_offset_minutes": -300
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.facebook.metrics.interested_count"
                          ],
                          "categories": [],
                          "community_id": null,
                          "cover_url": "https://scontent.ftol2-1.fna.fbcdn.net/v/t39.30808-6/866591974_1157426943381928_6760248865572493930_n.jpg?stp=c206.0.1508.1005a_dst-jpg_tt6&cstp=mx1508x1005&ctp=s1508x1005&_nc_cat=107&_nc_map=urlgen_bucketless&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                          "description": null,
                          "end_at": null,
                          "hosts": [],
                          "id": "769677042050918",
                          "is_online": false,
                          "metrics": {
                            "attendee_count": 1
                          },
                          "name": "Sunday Jazz Service",
                          "parent_id": null,
                          "place": {
                            "address": null,
                            "city": null,
                            "country_code": null,
                            "id": null,
                            "latitude": null,
                            "longitude": null,
                            "name": "Eliaskirken, Vesterbrogade 49, 1620 Copenhagen, Denmark",
                            "url": null
                          },
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "city_id": null,
                              "date_text": "Sun, Nov 8 at 1:00 PM CET and 2 more",
                              "frequency": null,
                              "metrics": {
                                "interested_count": 1400,
                                "response_count": null
                              },
                              "occurrence_count": null,
                              "price_text": null,
                              "ticket_provider": null
                            }
                          },
                          "start_at": "2025-11-02T12:00:00Z",
                          "status": "ongoing",
                          "ticket_url": null,
                          "time_zone": null,
                          "unknown_fields": [
                            "hosts",
                            "categories"
                          ],
                          "url": "https://www.facebook.com/events/769677042050918/",
                          "utc_offset_minutes": 60
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1374,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookSearch_eventsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Events by keyword, anywhere or in one city",
        "tags": [
          "Facebook Events"
        ],
        "x-socialtap-endpoint": "facebook.search_events",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 1800,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Facebook's ranking of the results, not by date",
          "page_max": 20,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "event",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/search_groups": {
      "get": {
        "description": "Returns the Facebook groups a web search finds for a topic, place or name, with each group's link, vanity name, title and description. Its privacy is included when the search index shows it. Add fill=true for each group's full, live record in the same response: ID, exact member count, privacy, rules, admins and activity. Page through the results with the cursor.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/search_groups/ (Markdown: https://socialtap.dev/docs/reference/facebook/search_groups/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/search_groups/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/search_groups/"
        },
        "operationId": "facebook.search_groups.list",
        "parameters": [
          {
            "description": "Words to find Facebook groups by, as a web search reads them: a topic, a place, a group's name (gardening, buy and sell houston, \"addicted to gardening\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and an operator that narrows to a page's title, text or link (intitle:, inurl:, intext:, url:) reads as its words.",
            "example": "gardening",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find Facebook groups by, as a web search reads them: a topic, a place, a group's name (gardening, buy and sell houston, \"addicted to gardening\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and an operator that narrows to a page's title, text or link (intitle:, inurl:, intext:, url:) reads as its words.",
              "examples": [
                "gardening"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "community.title",
                            "community.description"
                          ],
                          "community": {
                            "avatar_url": null,
                            "description": "Visit harvestsavvy.com to learn Everything Gardening! This online community is for all plant lovers, gardening and farming enthusiasts focused on sharing...",
                            "id": null,
                            "metrics": {
                              "member_count": null
                            },
                            "name": "youreverythinggardening",
                            "privacy": null,
                            "title": "Everything Gardening",
                            "url": "https://www.facebook.com/groups/youreverythinggardening/"
                          },
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.facebook.com/groups/youreverythinggardening/",
                          "place": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "account_type": null,
                              "like_count": null,
                              "place": null,
                              "talking_about_count": null,
                              "were_here_count": null
                            }
                          },
                          "position": 0,
                          "post": null,
                          "profile": null,
                          "snippet": "Visit harvestsavvy.com to learn Everything Gardening! This online community is for all plant lovers, gardening and farming enthusiasts focused on sharing...",
                          "sound": null,
                          "title": "Everything Gardening - Facebook",
                          "type": "community",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/groups/youreverythinggardening/"
                        },
                        {
                          "approximate_fields": [
                            "community.title",
                            "community.description"
                          ],
                          "community": {
                            "avatar_url": null,
                            "description": "We provide some information about plant guides, lawn cares, and gardening tools to better help your organic garden grow 🌻 Note: Please keep in mind that this is a Facebook page for a group of people interested in gardening and landscaping.",
                            "id": null,
                            "metrics": {
                              "member_count": null
                            },
                            "name": null,
                            "privacy": null,
                            "title": "Gardening",
                            "url": "https://www.facebook.com/groups/2541811060/"
                          },
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.facebook.com/groups/2541811060/",
                          "place": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "account_type": null,
                              "like_count": null,
                              "place": null,
                              "talking_about_count": null,
                              "were_here_count": null
                            }
                          },
                          "position": 1,
                          "post": null,
                          "profile": null,
                          "snippet": "We provide some information about plant guides, lawn cares, and gardening tools to better help your organic garden grow 🌻 Note: Please keep in mind that this is a Facebook page for a group of people interested in gardening and landscaping.",
                          "sound": null,
                          "title": "Gardening - Facebook",
                          "type": "community",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/groups/2541811060/"
                        },
                        {
                          "approximate_fields": [
                            "community.title",
                            "community.description"
                          ],
                          "community": {
                            "avatar_url": null,
                            "description": "With the gardening season upon us now, we are looking to take on more garden maintenance customers for this season There are only very limited slots available, with that being said we are also looking to take on one off jobs throughout the season. This can be from full garden tid…",
                            "id": null,
                            "metrics": {
                              "member_count": null
                            },
                            "name": null,
                            "privacy": null,
                            "title": "SM GARDENING",
                            "url": "https://www.facebook.com/groups/543243157060853/"
                          },
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://business.facebook.com/groups/543243157060853/",
                          "place": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "account_type": null,
                              "like_count": null,
                              "place": null,
                              "talking_about_count": null,
                              "were_here_count": null
                            }
                          },
                          "position": 2,
                          "post": null,
                          "profile": null,
                          "snippet": "With the gardening season upon us now, we are looking to take on more garden maintenance customers for this season There are only very limited slots available, with that being said we are also looking to take on one off jobs throughout the season. This can be from full garden tid…",
                          "sound": null,
                          "title": "SM GARDENING | Facebook",
                          "type": "community",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/groups/543243157060853/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1127,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookSearch_groupsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Groups by topic, place or name",
        "tags": [
          "Facebook"
        ],
        "x-socialtap-endpoint": "facebook.search_groups",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/search_listings": {
      "get": {
        "description": "Searches public Facebook Marketplace listings by keyword around a place, given as coordinates or a Marketplace location. Each result has its title, price with the struck-through earlier one, currency, availability, main photo, seller, city, category, the day it was listed and delivery options, and vehicles their mileage. Filter by radius, price, condition, days listed, availability, delivery method and category, and sort by relevance, newest, distance or price.\n\nReturns `{data, page, meta}`: `data` holds up to 30 `Product` items (Facebook calls it a listing) (the shared schema, the same on every platform), Marketplace's Suggested order with sort=relevance (the default), the closest to the place first with sort=nearest, the latest listed first, by the day: later pages can hold newer listings with sort=newest, the lowest price first with sort=price_asc, the highest price first with sort=price_desc. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/search_listings/ (Markdown: https://socialtap.dev/docs/reference/facebook/search_listings/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/search_listings/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/search_listings/"
        },
        "operationId": "facebook.search_listings.list",
        "parameters": [
          {
            "description": "Keywords to search listings for. Marketplace also returns close matches.",
            "example": "couch",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Keywords to search listings for. Marketplace also returns close matches.",
              "examples": [
                "couch"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Latitude of the place to search around (WGS 84 degrees), with lng; or use location.",
            "example": "30.2677",
            "in": "query",
            "name": "lat",
            "schema": {
              "description": "Latitude of the place to search around (WGS 84 degrees), with lng; or use location.",
              "examples": [
                30.2677
              ],
              "format": "double",
              "maximum": 90,
              "minimum": -90,
              "type": "number"
            }
          },
          {
            "description": "Longitude of the place to search around (WGS 84 degrees), with lat; or use location.",
            "example": "-97.7475",
            "in": "query",
            "name": "lng",
            "schema": {
              "description": "Longitude of the place to search around (WGS 84 degrees), with lat; or use location.",
              "examples": [
                -97.7475
              ],
              "format": "double",
              "maximum": 180,
              "minimum": -180,
              "type": "number"
            }
          },
          {
            "description": "The place to search around, instead of lat and lng: a Marketplace place ID (platform_specific.facebook.location_id of a listing there, such as 106224666074625), the city name in Marketplace's links (austin, nyc, paris) or such a link (https://www.facebook.com/marketplace/austin/). An unknown one returns not_found.",
            "example": "austin",
            "in": "query",
            "name": "location",
            "schema": {
              "description": "The place to search around, instead of lat and lng: a Marketplace place ID (platform_specific.facebook.location_id of a listing there, such as 106224666074625), the city name in Marketplace's links (austin, nyc, paris) or such a link (https://www.facebook.com/marketplace/austin/). An unknown one returns not_found.",
              "examples": [
                "austin"
              ],
              "maxLength": 300,
              "type": "string"
            }
          },
          {
            "description": "How far around the place to search, in kilometers (default 65). Marketplace widens a search with few results near the place.",
            "example": "",
            "in": "query",
            "name": "radius_km",
            "schema": {
              "description": "How far around the place to search, in kilometers (default 65). Marketplace widens a search with few results near the place.",
              "format": "int64",
              "maximum": 805,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Only listings at this price or above, in major units of the local currency.",
            "example": "",
            "in": "query",
            "name": "min_price",
            "schema": {
              "description": "Only listings at this price or above, in major units of the local currency.",
              "format": "double",
              "maximum": 2147483647,
              "minimum": 0,
              "type": "number"
            }
          },
          {
            "description": "Only listings at this price or below, in major units of the local currency. Omitted or 0 means no upper bound, so it cannot select only free listings.",
            "example": "",
            "in": "query",
            "name": "max_price",
            "schema": {
              "description": "Only listings at this price or below, in major units of the local currency. Omitted or 0 means no upper bound, so it cannot select only free listings.",
              "format": "double",
              "maximum": 2147483647,
              "minimum": 0,
              "type": "number"
            }
          },
          {
            "description": "Order of the results. relevance (default): Marketplace's Suggested order. newest: the latest listed first. nearest: the closest to the place first. price_asc, price_desc: the lowest or the highest price first.",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "relevance",
              "description": "Order of the results. relevance (default): Marketplace's Suggested order. newest: the latest listed first. nearest: the closest to the place first. price_asc, price_desc: the lowest or the highest price first.",
              "enum": [
                "relevance",
                "newest",
                "nearest",
                "price_asc",
                "price_desc"
              ],
              "type": "string"
            }
          },
          {
            "description": "The window the ranking counts over, in days back from the platform's latest update (each endpoint lists its own). Only listings Marketplace counts as listed in the last 1, 7 or 30 days, in whole calendar days (today counts, so 1 can include yesterday's). All dates when omitted.",
            "example": "7",
            "in": "query",
            "name": "period",
            "schema": {
              "description": "The window the ranking counts over, in days back from the platform's latest update (each endpoint lists its own). Only listings Marketplace counts as listed in the last 1, 7 or 30 days, in whole calendar days (today counts, so 1 can include yesterday's). All dates when omitted.",
              "enum": [
                "1",
                "7",
                "30"
              ],
              "examples": [
                "7"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only listings in these conditions, comma-separated: new, used_like_new, used_good, used_fair. All when omitted.",
            "example": "new,used_good",
            "in": "query",
            "name": "condition",
            "schema": {
              "description": "Only listings in these conditions, comma-separated: new, used_like_new, used_good, used_fair. All when omitted.",
              "examples": [
                "new,used_good"
              ],
              "maxLength": 60,
              "type": "string"
            }
          },
          {
            "description": "available (default): listings for sale now. sold: listings marked sold or with a sale pending.",
            "example": "",
            "in": "query",
            "name": "availability",
            "schema": {
              "description": "available (default): listings for sale now. sold: listings marked sold or with a sale pending.",
              "enum": [
                "available",
                "sold"
              ],
              "type": "string"
            }
          },
          {
            "description": "all (default), only listings the buyer can pick up (local_pickup), or only those the seller ships (shipping), which can come from far away.",
            "example": "",
            "in": "query",
            "name": "delivery_method",
            "schema": {
              "description": "all (default), only listings the buyer can pick up (local_pickup), or only those the seller ships (shipping), which can come from far away.",
              "enum": [
                "all",
                "local_pickup",
                "shipping"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only listings in this Marketplace category (data[].category_id of a listing, such as 1658310421102081 for Bicycles).",
            "example": "",
            "in": "query",
            "name": "category_id",
            "schema": {
              "description": "Only listings in this Marketplace category (data[].category_id of a listing, such as 1658310421102081 for Bicycles).",
              "maxLength": 25,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 30,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 30,
              "maximum": 30,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "attributes": [],
                          "availability": "in_stock",
                          "category": null,
                          "category_id": "1583634935226685",
                          "condition": null,
                          "condition_label": null,
                          "country_code": null,
                          "currency": "USD",
                          "description": null,
                          "id": "2453157098823358",
                          "max_price": 150,
                          "media": [],
                          "original_price": 199,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "delivery_types": [
                                "in_person"
                              ],
                              "is_buy_now_enabled": null,
                              "is_local_pickup": true,
                              "latitude": null,
                              "location": "Austin, TX",
                              "location_id": "106224666074625",
                              "longitude": null,
                              "postal_code": null,
                              "price_period": null,
                              "published_at": "2026-08-08T23:19:48Z",
                              "seller_joined_at": null,
                              "seller_rating": null,
                              "seller_rating_count": null
                            }
                          },
                          "price": 150,
                          "seller": {
                            "avatar_url": null,
                            "display_name": "Emma Lacayo",
                            "id": "pfbid028Sb5xn7vbqx7e9FMM94r2aYCMPpRvZ3tqQrtarsZFL3C4J9qjTrG5yKqfHATwFV7l",
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "shipping": {
                            "fee": null,
                            "is_offered": false
                          },
                          "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.84726-6/770825152_1048174351401284_1140858447926294965_n.jpg?stp=c0.87.526.526a_dst-jpg_p526x395_tt6&_nc_cat=104&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7…",
                          "title": "Couch",
                          "type": "listing",
                          "unknown_fields": [
                            "attributes",
                            "media"
                          ],
                          "url": "https://www.facebook.com/marketplace/item/2453157098823358/"
                        },
                        {
                          "approximate_fields": [],
                          "attributes": [],
                          "availability": "in_stock",
                          "category": null,
                          "category_id": "1583634935226685",
                          "condition": null,
                          "condition_label": null,
                          "country_code": null,
                          "currency": "USD",
                          "description": null,
                          "id": "2058904701477440",
                          "max_price": 0,
                          "media": [],
                          "original_price": 50,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "delivery_types": [
                                "in_person"
                              ],
                              "is_buy_now_enabled": null,
                              "is_local_pickup": true,
                              "latitude": null,
                              "location": "Austin, TX",
                              "location_id": "106224666074625",
                              "longitude": null,
                              "postal_code": null,
                              "price_period": null,
                              "published_at": "2026-10-30T22:41:54Z",
                              "seller_joined_at": null,
                              "seller_rating": null,
                              "seller_rating_count": null
                            }
                          },
                          "price": 0,
                          "seller": {
                            "avatar_url": null,
                            "display_name": "Joseph Nelson",
                            "id": "pfbid02LXiNxAkFuVeVVp6m2pNoHNMKLHXNfewhx35WhL5p3DJTrxZEnmKBiEUGxhHqnexl",
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "shipping": {
                            "fee": null,
                            "is_offered": false
                          },
                          "thumbnail_url": "https://scontent-atl3-1.xx.fbcdn.net/v/t39.84726-6/865992404_2598858703877779_3582095600555384707_n.jpg?stp=c123.0.540.540a_dst-jpg_p180x540_tt6&_nc_cat=106&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-1.xx&_nc_gid=SCRUBBED&_nc_ss=…",
                          "title": "Sectional couch",
                          "type": "listing",
                          "unknown_fields": [
                            "attributes",
                            "media"
                          ],
                          "url": "https://www.facebook.com/marketplace/item/2058904701477440/"
                        },
                        {
                          "approximate_fields": [],
                          "attributes": [],
                          "availability": "in_stock",
                          "category": null,
                          "category_id": "1583634935226685",
                          "condition": null,
                          "condition_label": null,
                          "country_code": null,
                          "currency": "USD",
                          "description": null,
                          "id": "1074423591747937",
                          "max_price": 300,
                          "media": [],
                          "original_price": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "delivery_types": [
                                "in_person",
                                "public_meetup"
                              ],
                              "is_buy_now_enabled": null,
                              "is_local_pickup": true,
                              "latitude": null,
                              "location": "Austin, TX",
                              "location_id": "106224666074625",
                              "longitude": null,
                              "postal_code": null,
                              "price_period": null,
                              "published_at": "2026-08-31T16:04:49Z",
                              "seller_joined_at": null,
                              "seller_rating": null,
                              "seller_rating_count": null
                            }
                          },
                          "price": 300,
                          "seller": {
                            "avatar_url": null,
                            "display_name": "Jayden Collon",
                            "id": "pfbid0k18cWpao4WmR78cmx1CL23UERiW9rwJXQ3xLJgMu1ktX7xtacBKxFb8EakqyUA9ul",
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "shipping": {
                            "fee": null,
                            "is_offered": false
                          },
                          "thumbnail_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.84726-6/789581205_1093657659864910_5715105961279626720_n.jpg?stp=c0.87.526.526a_dst-jpg_p526x395_tt6&_nc_cat=104&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=14&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7…",
                          "title": "grey sofa/loveseat,couch with hidden compartments and can oull out to make longer",
                          "type": "listing",
                          "unknown_fields": [
                            "attributes",
                            "media"
                          ],
                          "url": "https://www.facebook.com/marketplace/item/1074423591747937/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1593,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookSearch_listingsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Listings by keyword and location, with prices",
        "tags": [
          "Facebook Marketplace"
        ],
        "x-socialtap-endpoint": "facebook.search_listings",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 10800,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Marketplace's Suggested order",
          "orders": {
            "nearest": "the closest to the place first",
            "newest": "the latest listed first, by the day: later pages can hold newer listings",
            "price_asc": "the lowest price first",
            "price_desc": "the highest price first",
            "relevance": "Marketplace's Suggested order"
          },
          "page_max": 30,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "product",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/search_places": {
      "get": {
        "description": "Returns the places Facebook Marketplace's location picker offers for a city, neighborhood or postal code, with the ID a Marketplace search takes. Each place has its name, coordinates, the city and postal code Facebook gives it, the area line the picker shows, whether Facebook calls it a city, and its check-in count. Filter to one country, or rank around coordinates to tell places of the same name apart.\n\nReturns `{data, page, meta}`: `data` holds up to 10 `Place` items (the shared schema, the same on every platform), most relevant first, as Marketplace's location picker ranks them. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/search_places/ (Markdown: https://socialtap.dev/docs/reference/facebook/search_places/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/search_places/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/search_places/"
        },
        "operationId": "facebook.search_places.list",
        "parameters": [
          {
            "description": "What to look for, as typed into Marketplace's location picker: a city, neighborhood or postal code. Matched by name, case-insensitive; a place ID matches nothing.",
            "example": "Austin",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to look for, as typed into Marketplace's location picker: a city, neighborhood or postal code. Matched by name, case-insensitive; a place ID matches nothing.",
              "examples": [
                "Austin"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only places in this country: an ISO 3166-1 alpha-2 code such as US. Every country when omitted; Facebook ignores a code it does not know.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only places in this country: an ISO 3166-1 alpha-2 code such as US. Every country when omitted; Facebook ignores a code it does not know.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Latitude (WGS 84 degrees) to rank places near, with lng: of two Springfields, the closer comes first.",
            "example": "42.1",
            "in": "query",
            "name": "lat",
            "schema": {
              "description": "Latitude (WGS 84 degrees) to rank places near, with lng: of two Springfields, the closer comes first.",
              "examples": [
                42.1
              ],
              "format": "double",
              "maximum": 90,
              "minimum": -90,
              "type": "number"
            }
          },
          {
            "description": "Longitude (WGS 84 degrees) to rank places near, with lat.",
            "example": "-72.59",
            "in": "query",
            "name": "lng",
            "schema": {
              "description": "Longitude (WGS 84 degrees) to rank places near, with lat.",
              "examples": [
                -72.59
              ],
              "format": "double",
              "maximum": 180,
              "minimum": -180,
              "type": "number"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 10,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 10,
              "maximum": 10,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "account": null,
                          "address": "Austin, IL",
                          "approximate_fields": [
                            "platform_specific.facebook.checkin_count"
                          ],
                          "category": null,
                          "city": "Chicago",
                          "country_code": null,
                          "description": null,
                          "id": "108120015875983",
                          "images": [],
                          "latitude": 41.894086,
                          "longitude": -87.763202,
                          "metrics": {
                            "image_count": null,
                            "post_count": null,
                            "review_count": null
                          },
                          "name": "Austin",
                          "phone": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "checkin_count": 25676
                            }
                          },
                          "postal_code": "60644-1112",
                          "price_range": null,
                          "type": "area",
                          "unknown_fields": [
                            "images"
                          ],
                          "url": "https://www.facebook.com/marketplace/108120015875983/",
                          "website_url": null
                        },
                        {
                          "account": null,
                          "address": "Austin, GA",
                          "approximate_fields": [
                            "platform_specific.facebook.checkin_count"
                          ],
                          "category": null,
                          "city": "Marietta",
                          "country_code": null,
                          "description": null,
                          "id": "312180006098697",
                          "images": [],
                          "latitude": 33.955058,
                          "longitude": -84.529634,
                          "metrics": {
                            "image_count": null,
                            "post_count": null,
                            "review_count": null
                          },
                          "name": "Austin",
                          "phone": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "checkin_count": 162
                            }
                          },
                          "postal_code": "30060-1862",
                          "price_range": null,
                          "type": "area",
                          "unknown_fields": [
                            "images"
                          ],
                          "url": "https://www.facebook.com/marketplace/312180006098697/",
                          "website_url": null
                        },
                        {
                          "account": null,
                          "address": null,
                          "approximate_fields": [],
                          "category": "City",
                          "city": "Austin",
                          "country_code": null,
                          "description": null,
                          "id": "106224666074625",
                          "images": [],
                          "latitude": 30.2677,
                          "longitude": -97.7475,
                          "metrics": {
                            "image_count": null,
                            "post_count": null,
                            "review_count": null
                          },
                          "name": "Austin, Texas",
                          "phone": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "checkin_count": null
                            }
                          },
                          "postal_code": "78701",
                          "price_range": null,
                          "type": "area",
                          "unknown_fields": [
                            "images"
                          ],
                          "url": "https://www.facebook.com/marketplace/106224666074625/",
                          "website_url": null
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 297,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookSearch_placesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Location IDs for a city or postal code",
        "tags": [
          "Facebook Marketplace"
        ],
        "x-socialtap-endpoint": "facebook.search_places",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "most relevant first, as Marketplace's location picker ranks them",
          "page_max": 10,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "place",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/search_posts": {
      "get": {
        "description": "Returns public Facebook posts that a web search finds for your keywords, with each post's link, account, date and opening text. Add fill=true to get each post's full, live Facebook record in the same response: post ID, text, media, exact reaction, comment and share counts and publish time. media=video finds videos instead. Page through the results with the cursor.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/search_posts/ (Markdown: https://socialtap.dev/docs/reference/facebook/search_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/search_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/search_posts/"
        },
        "operationId": "facebook.search_posts.list",
        "parameters": [
          {
            "description": "Words to find Facebook posts by, as a web search reads them: a topic, a product, a brand or a place (coffee roaster, electric vehicle charging, \"nancy grace roman\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and an operator that narrows to a page's title, text or link (intitle:, inurl:, intext:, url:) reads as its words.",
            "example": "coffee roaster",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find Facebook posts by, as a web search reads them: a topic, a product, a brand or a place (coffee roaster, electric vehicle charging, \"nancy grace roman\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and an operator that narrows to a page's title, text or link (intitle:, inurl:, intext:, url:) reads as its words.",
              "examples": [
                "coffee roaster"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "video: only the videos of Pages and profiles (facebook.com/<name>/videos/…), found the same way, so fill=true gets each video's post record with its views. All posts when omitted.",
            "example": "",
            "in": "query",
            "name": "media",
            "schema": {
              "description": "video: only the videos of Pages and profiles (facebook.com/<name>/videos/…), found the same way, so fill=true gets each video's post record with its views. All posts when omitted.",
              "enum": [
                "video"
              ],
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.facebook.com/arcaderoasters/posts/welcome-to-the-roasting-part-of-arcade-coffee-roasters-all-our-coffee-is-freshly/877760954366326/",
                          "place": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "account_type": null,
                              "like_count": null,
                              "place": null,
                              "talking_about_count": null,
                              "were_here_count": null
                            }
                          },
                          "position": 0,
                          "post": {
                            "author": {
                              "avatar_url": null,
                              "display_name": "Arcade Coffee Roasters",
                              "id": null,
                              "is_verified": null,
                              "url": "https://www.facebook.com/arcaderoasters",
                              "username": "arcaderoasters"
                            },
                            "id": null,
                            "metrics": {
                              "comment_count": null,
                              "like_count": null,
                              "quote_count": null,
                              "repost_count": null,
                              "save_count": null,
                              "share_count": null,
                              "view_count": null
                            },
                            "published_at": null,
                            "text": null,
                            "thumbnail_url": null,
                            "title": null,
                            "url": "https://www.facebook.com/arcaderoasters/posts/877760954366326"
                          },
                          "profile": null,
                          "snippet": "Arcade Coffee Roasters. 2,569 likes · 25 talking about this · 79 were here. Arcade Coffee Roasters is a Specialty Coffee Company located in the Inland Empire.",
                          "sound": null,
                          "title": "Arcade Coffee Roasters | Facebook",
                          "type": "post",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/arcaderoasters/posts/877760954366326"
                        },
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.facebook.com/reddoorroaster/posts/740482067782696/",
                          "place": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "account_type": null,
                              "like_count": null,
                              "place": null,
                              "talking_about_count": null,
                              "were_here_count": null
                            }
                          },
                          "position": 1,
                          "post": {
                            "author": {
                              "avatar_url": null,
                              "display_name": "Red Door Coffee Roaster",
                              "id": null,
                              "is_verified": null,
                              "url": "https://www.facebook.com/reddoorroaster",
                              "username": "reddoorroaster"
                            },
                            "id": null,
                            "metrics": {
                              "comment_count": null,
                              "like_count": null,
                              "quote_count": null,
                              "repost_count": null,
                              "save_count": null,
                              "share_count": null,
                              "view_count": null
                            },
                            "published_at": null,
                            "text": null,
                            "thumbnail_url": null,
                            "title": null,
                            "url": "https://www.facebook.com/reddoorroaster/posts/740482067782696"
                          },
                          "profile": null,
                          "snippet": "Red Door Coffee Roaster, Center Valley. 624 likes · 1 talking about this · 19 were here. Micro-roaster of fine coffees � NEW! Coffee Shop: Located at the Trolley Barn Public Market 116 E Broad...",
                          "sound": null,
                          "title": "Red Door Coffee Roaster | Center Valley PA | Facebook",
                          "type": "post",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/reddoorroaster/posts/740482067782696"
                        },
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.facebook.com/DalianAmazonCoffeeRoaster/posts/dl-a721-sbb-1kg-coffee-roaster/973590226143545/",
                          "place": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "account_type": null,
                              "like_count": null,
                              "place": null,
                              "talking_about_count": null,
                              "were_here_count": null
                            }
                          },
                          "position": 2,
                          "post": {
                            "author": {
                              "avatar_url": null,
                              "display_name": "Coffee Roaster",
                              "id": null,
                              "is_verified": null,
                              "url": "https://www.facebook.com/DalianAmazonCoffeeRoaster",
                              "username": "DalianAmazonCoffeeRoaster"
                            },
                            "id": null,
                            "metrics": {
                              "comment_count": null,
                              "like_count": null,
                              "quote_count": null,
                              "repost_count": null,
                              "save_count": null,
                              "share_count": null,
                              "view_count": null
                            },
                            "published_at": null,
                            "text": null,
                            "thumbnail_url": null,
                            "title": null,
                            "url": "https://www.facebook.com/DalianAmazonCoffeeRoaster/posts/973590226143545"
                          },
                          "profile": null,
                          "snippet": "Coffee Roaster, Dalian. 326 likes. Dalian Amazon Coffee Co.,Ltd, a professional Coffee Roaster 's manufacturer, Nine years' Alibaba Gol",
                          "sound": null,
                          "title": "Coffee Roaster | Dalian | Facebook",
                          "type": "post",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/DalianAmazonCoffeeRoaster/posts/973590226143545"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1131,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookSearch_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Public posts and videos by keyword",
        "tags": [
          "Facebook"
        ],
        "x-socialtap-endpoint": "facebook.search_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/search_profiles": {
      "get": {
        "description": "Returns the Facebook Pages and people a web search finds for a name, a business type or a place, with each one's username and profile link. Each also has what the search index shows of it: name, a Page's about text, followers, likes, check-ins and city. Add fill=true for each account's full, live Facebook profile in the same response: ID, exact counts, verified badge, picture and contact details. account_type narrows the results to Pages or to people.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/search_profiles/ (Markdown: https://socialtap.dev/docs/reference/facebook/search_profiles/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/search_profiles/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/search_profiles/"
        },
        "operationId": "facebook.search_profiles.list",
        "parameters": [
          {
            "description": "Words to find Facebook accounts by, as a web search reads them: a Page's or a person's name, a business type and a place (coffee roaster, yoga studio austin, john smith, \"national geographic\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and intitle:, inurl: and intext: count as plain words.",
            "example": "coffee roaster",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find Facebook accounts by, as a web search reads them: a Page's or a person's name, a business type and a place (coffee roaster, yoga studio austin, john smith, \"national geographic\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and intitle:, inurl: and intext: count as plain words.",
              "examples": [
                "coffee roaster"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Only accounts of this kind: page (a Page, or a person in professional mode, as Facebook describes both alike) or person. Both when omitted, which finds mostly Pages: use person to find people.",
            "example": "person",
            "in": "query",
            "name": "account_type",
            "schema": {
              "description": "Only accounts of this kind: page (a Page, or a person in professional mode, as Facebook describes both alike) or person. Both when omitted, which finds mostly Pages: use person to find people.",
              "enum": [
                "page",
                "person"
              ],
              "examples": [
                "person"
              ],
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "platform_specific.facebook.place",
                            "platform_specific.facebook.talking_about_count",
                            "platform_specific.facebook.were_here_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.facebook.com/coffeeroasterlnk/",
                          "place": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "account_type": "page",
                              "like_count": null,
                              "place": "Lincoln",
                              "talking_about_count": 159,
                              "were_here_count": 449
                            }
                          },
                          "position": 0,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "Serving fresh roasted coffee to Lincoln and beyond since 1995. 🖤 Locally owned. Community loved.",
                            "display_name": "The Coffee Roaster",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": 4063,
                              "following_count": null,
                              "post_count": null,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://www.facebook.com/coffeeroasterlnk",
                            "username": "coffeeroasterlnk"
                          },
                          "snippet": "The Coffee Roaster, Lincoln. 4,063 followers · 159 talking about this · 449 were here. Serving fresh roasted coffee to Lincoln and beyond since 1995. 🖤 Locally owned. Community loved.",
                          "sound": null,
                          "title": "The Coffee Roaster | Lincoln NE | Facebook",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/coffeeroasterlnk"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.facebook.place",
                            "platform_specific.facebook.talking_about_count",
                            "platform_specific.facebook.were_here_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.facebook.com/thecoffeeroastercy/",
                          "place": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "account_type": "page",
                              "like_count": null,
                              "place": "Paralimni",
                              "talking_about_count": 16,
                              "were_here_count": 122
                            }
                          },
                          "position": 1,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "The Coffee Roasters has been importing speciality coffee since 2007. In 2020 we started an artisan roastery",
                            "display_name": "The Coffee Roaster",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": 1225,
                              "following_count": null,
                              "post_count": null,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://www.facebook.com/thecoffeeroastercy",
                            "username": "thecoffeeroastercy"
                          },
                          "snippet": "The Coffee Roaster, Paralimni. 1,225 followers · 16 talking about this · 122 were here. The Coffee Roasters has been importing speciality coffee since 2007. In 2020 we started an artisan roastery...",
                          "sound": null,
                          "title": "The Coffee Roaster | Paralimni | Facebook",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/thecoffeeroastercy"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.facebook.talking_about_count",
                            "platform_specific.facebook.were_here_count",
                            "profile.metrics.follower_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.facebook.com/thecoffeeroaster/",
                          "place": null,
                          "platform": "facebook",
                          "platform_specific": {
                            "facebook": {
                              "account_type": "page",
                              "like_count": null,
                              "place": null,
                              "talking_about_count": 39,
                              "were_here_count": 63
                            }
                          },
                          "position": 2,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "The Coffee Roaster Group operates TCR Cafe @ NUS AS8, TCR Academy and baking unit The Baker's Gallery",
                            "display_name": "The Coffee Roaster",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": 2865,
                              "following_count": null,
                              "post_count": null,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://www.facebook.com/thecoffeeroaster",
                            "username": "thecoffeeroaster"
                          },
                          "snippet": "The Coffee Roaster. 2,865 followers · 39 talking about this · 63 were here. The Coffee Roaster Group operates TCR Cafe @ NUS AS8, TCR Academy and baking unit The Baker's Gallery",
                          "sound": null,
                          "title": "The Coffee Roaster (@thecoffeeroaster)",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://www.facebook.com/thecoffeeroaster"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1267,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookSearch_profilesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Pages and people by name, niche or place",
        "tags": [
          "Facebook"
        ],
        "x-socialtap-endpoint": "facebook.search_profiles",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/facebook/transcript": {
      "get": {
        "description": "Returns the timed transcript of a public Facebook video or reel from its link or ID, from its captions or, when it has none, its audio. Captions are the uploaded track first, then Facebook's auto-generated one, and a video without either is transcribed with speech-to-text. Each segment has its start and end time, and text holds the whole transcript.\n\nReturns `{data, meta}`: `data` is a `Transcript` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit (captions) or 2 credits + 2 per started minute of media (speech-to-text) per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/facebook/transcript/ (Markdown: https://socialtap.dev/docs/reference/facebook/transcript/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/facebook/transcript/index.md)",
          "url": "https://socialtap.dev/docs/reference/facebook/transcript/"
        },
        "operationId": "facebook.transcript.get",
        "parameters": [
          {
            "description": "Facebook video URL (reel, watch, page video, video.php, m./mbasic./web. hosts, fb.watch and share/v|r links) or a numeric video ID.",
            "example": "https://www.facebook.com/reel/1803909017420449/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Facebook video URL (reel, watch, page video, video.php, m./mbasic./web. hosts, fb.watch and share/v|r links) or a numeric video ID.",
              "examples": [
                "https://www.facebook.com/reel/1803909017420449"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "available_languages": [
                          "en-US"
                        ],
                        "duration_ms": 59861,
                        "id": "1803909017420449",
                        "is_auto_generated": false,
                        "language": "en-US",
                        "platform": "facebook",
                        "platform_specific": {},
                        "segments": [
                          {
                            "end_ms": 4000,
                            "start_ms": 33,
                            "text": "But the standard that we should continuously aspire to exceed,"
                          },
                          {
                            "end_ms": 7166,
                            "start_ms": 4000,
                            "text": "which is why we are bringing that intensity, that discipline, that"
                          },
                          {
                            "end_ms": 11400,
                            "start_ms": 7166,
                            "text": "engineering ownership back to NASA, because great nations do not remain great"
                          }
                        ],
                        "source": "captions",
                        "text": "But the standard that we should continuously aspire to exceed, which is why we are bringing that intensity, that discipline, that engineering ownership back to NASA, because great nations do not remain great by being caretakers of history, but by continuously making history. We h…",
                        "url": "https://www.facebook.com/reel/1803909017420449/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "facebook",
                        "source": "captions",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 713,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "1803909017420449",
                          "url": "https://www.facebook.com/reel/1803909017420449/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FacebookTranscriptResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "no_transcript": {
                    "$ref": "#/components/examples/no_transcript"
                  },
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.\n\n`no_transcript`: The video or audio exists but has no transcript: no caption track and no speech to transcribe. Do not retry. If the platform offers other languages, try one with lang.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Timed transcript of a video or reel",
        "tags": [
          "Facebook"
        ],
        "x-socialtap-endpoint": "facebook.transcript",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 122,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "captions"
            },
            {
              "credits": 2,
              "label": "2 credits + 2 per started minute of media",
              "max": 122,
              "per": 2,
              "source": "asr",
              "unit": "media_minute",
              "unit_max": 60
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "transcript",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/google/ad": {
      "get": {
        "description": "Returns one ad from Google's public Ads Transparency Center by its link or creative ID, with its advertiser, creative and where and when it ran. You also get whether the advertiser verified its identity, who paid, the format, each variation's image (or a local text ad's headline, description and link), the first and last day shown, the countries and the topic Google labels it with. Ads shown in Europe and election ads add Google's impressions per country and per service and the kinds of audience criteria used. Election ads also add their spend range and age, gender and location targeting.\n\nReturns `{data, meta}`: `data` is a `Ad` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/google/ad/ (Markdown: https://socialtap.dev/docs/reference/google/ad/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/google/ad/index.md)",
          "url": "https://socialtap.dev/docs/reference/google/ad/"
        },
        "operationId": "google.ad.get",
        "parameters": [
          {
            "description": "The ad's Google Ads Transparency Center link (adstransparency.google.com/advertiser/AR…/creative/CR…), its old political ads report link, or its creative ID (CR…).",
            "example": "https://adstransparency.google.com/advertiser/AR07541154843046445057/creative/CR17778900238552006657?region=US&topic=political",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The ad's Google Ads Transparency Center link (adstransparency.google.com/advertiser/AR…/creative/CR…), its old political ads report link, or its creative ID (CR…).",
              "examples": [
                "https://adstransparency.google.com/advertiser/AR01614014350098432001/creative/CR07443539616616939521?region=US"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "advertiser": {
                          "avatar_url": null,
                          "display_name": "Republican National Committee",
                          "id": "AR07541154843046445057",
                          "is_verified": true,
                          "url": "https://adstransparency.google.com/advertiser/AR07541154843046445057",
                          "username": null
                        },
                        "approximate_fields": [
                          "platform_specific.google.regions[].first_shown_at",
                          "platform_specific.google.regions[].last_shown_at"
                        ],
                        "audience_size": null,
                        "country_codes": [
                          "US"
                        ],
                        "creatives": [
                          {
                            "body": null,
                            "cta_text": null,
                            "link_description": null,
                            "link_url": null,
                            "media": [
                              {
                                "alt_text": null,
                                "duration_ms": null,
                                "expires_at": null,
                                "height": null,
                                "thumbnail_url": null,
                                "type": "image",
                                "url": "https://tpc.googlesyndication.com/archive/simgad/18242167605449878359",
                                "width": null
                              }
                            ],
                            "title": null
                          }
                        ],
                        "first_shown_at": "2026-06-05T21:52:15Z",
                        "id": "CR17778900238552006657",
                        "impressions": {
                          "lower_bound": 500000,
                          "upper_bound": 600000
                        },
                        "is_active": null,
                        "is_political": true,
                        "languages": [],
                        "last_shown_at": "2026-06-24T19:04:54Z",
                        "paid_by": null,
                        "platform": "google",
                        "platform_specific": {
                          "google": {
                            "days_shown": 20,
                            "is_synthetic": false,
                            "product_category": null,
                            "regions": [
                              {
                                "country_code": "US",
                                "first_shown_at": "2026-06-05T00:00:00Z",
                                "impressions": {
                                  "lower_bound": 500000,
                                  "upper_bound": 600000
                                },
                                "last_shown_at": "2026-06-24T00:00:00Z",
                                "services": []
                              }
                            ],
                            "targeting": {
                              "age_ranges": [
                                "25-34",
                                "35-44",
                                "45-54"
                              ],
                              "criteria": [],
                              "excluded_age_ranges": [
                                "18-24"
                              ],
                              "excluded_genders": [],
                              "excluded_locations": [
                                {
                                  "country_code": "SC",
                                  "criterion_id": "2690",
                                  "full_name": "Seychelles",
                                  "name": "Seychelles"
                                },
                                {
                                  "country_code": "CV",
                                  "criterion_id": "2132",
                                  "full_name": "Cabo Verde",
                                  "name": "Cabo Verde"
                                },
                                {
                                  "country_code": "CH",
                                  "criterion_id": "2756",
                                  "full_name": "Switzerland",
                                  "name": "Switzerland"
                                }
                              ],
                              "genders": [
                                "male",
                                "female",
                                "unknown"
                              ],
                              "locations": [
                                {
                                  "country_code": "US",
                                  "criterion_id": "2840",
                                  "full_name": "United States",
                                  "name": "United States"
                                }
                              ]
                            },
                            "topic": null
                          }
                        },
                        "publisher_platforms": [],
                        "reach": null,
                        "spend": {
                          "currency": "USD",
                          "lower_bound": 5000,
                          "upper_bound": 6000
                        },
                        "type": "image",
                        "unknown_fields": [
                          "languages",
                          "publisher_platforms"
                        ],
                        "url": "https://adstransparency.google.com/advertiser/AR07541154843046445057/creative/CR17778900238552006657"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "google",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 420,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "ad",
                          "id": "CR17778900238552006657",
                          "url": "https://adstransparency.google.com/advertiser/AR07541154843046445057/creative/CR17778900238552006657"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/GoogleAdResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Advertiser, creative and where and when it ran",
        "tags": [
          "Google Ads Transparency Center"
        ],
        "x-socialtap-endpoint": "google.ad",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "ad",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/google/ads": {
      "get": {
        "description": "Returns the ads one advertiser ran on Google Search, YouTube, Maps, Play and Shopping, from the Ads Transparency Center, by advertiser ID or link. Each ad has its format, image, first and last day shown and days shown, with the advertiser's name and verification. Filter by country, format, service and dates, or list only election ads, which add their countries and Google's impressions and spend ranges and sort by impressions or spend. Ads come most recently shown first.\n\nReturns `{data, page, meta}`: `data` holds up to 40 `Ad` items (the shared schema, the same on every platform), last shown, most recent first with sort=newest (the default), last shown, least recent first (topic=political) with sort=oldest, most impressions first (topic=political) with sort=popular, most spent first (topic=political) with sort=spend. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/google/ads/ (Markdown: https://socialtap.dev/docs/reference/google/ads/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/google/ads/index.md)",
          "url": "https://socialtap.dev/docs/reference/google/ads/"
        },
        "operationId": "google.ads.list",
        "parameters": [
          {
            "description": "The advertiser: its Ads Transparency Center ID (AR…) or its page link (adstransparency.google.com/advertiser/AR…), in any case.",
            "example": "https://adstransparency.google.com/advertiser/AR01614014350098432001?region=US",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The advertiser: its Ads Transparency Center ID (AR…) or its page link (adstransparency.google.com/advertiser/AR…), in any case.",
              "examples": [
                "AR01614014350098432001"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only ads shown in this country. All countries when omitted; required with topic=political.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only ads shown in this country. All countries when omitted; required with topic=political.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "political: only the advertiser's election ads (the center's Political ads view), with their impressions and spend; needs country. Default: all.",
            "example": "",
            "in": "query",
            "name": "topic",
            "schema": {
              "default": "all",
              "description": "political: only the advertiser's election ads (the center's Political ads view), with their impressions and spend; needs country. Default: all.",
              "enum": [
                "all",
                "political"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only ads of this format. All formats when omitted.",
            "example": "",
            "in": "query",
            "name": "format",
            "schema": {
              "description": "Only ads of this format. All formats when omitted.",
              "enum": [
                "text",
                "image",
                "video"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only ads shown on this Google service. All services when omitted.",
            "example": "",
            "in": "query",
            "name": "service",
            "schema": {
              "description": "Only ads shown on this Google service. All services when omitted.",
              "enum": [
                "google_search",
                "google_maps",
                "google_play",
                "google_shopping",
                "youtube"
              ],
              "type": "string"
            }
          },
          {
            "description": "Order of the results. newest: most recently shown first (the center's order). With topic=political also oldest (least recently shown first), popular (most impressions first) and spend (most spent first).",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "newest",
              "description": "Order of the results. newest: most recently shown first (the center's order). With topic=political also oldest (least recently shown first), popular (most impressions first) and spend (most spent first).",
              "enum": [
                "newest",
                "oldest",
                "popular",
                "spend"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Ads count when they were shown during the window: an ad last shown (last_shown_at) before since is left out.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Ads count when they were shown during the window: an ad last shown (last_shown_at) before since is left out.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Ads count when they were shown during the window: an ad first shown (first_shown_at) at or after until is left out.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Ads count when they were shown during the window: an ad first shown (first_shown_at) at or after until is left out.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 40,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 40,
              "maximum": 40,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "advertiser": {
                            "avatar_url": null,
                            "display_name": "lululemon athletica canada inc.",
                            "id": "AR01614014350098432001",
                            "is_verified": true,
                            "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001",
                            "username": null
                          },
                          "approximate_fields": [
                            "creatives"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": null,
                              "cta_text": null,
                              "link_description": null,
                              "link_url": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": null,
                                  "height": null,
                                  "thumbnail_url": null,
                                  "type": "image",
                                  "url": "https://tpc.googlesyndication.com/archive/simgad/6465019125132301667",
                                  "width": null
                                }
                              ],
                              "title": null
                            }
                          ],
                          "first_shown_at": "2026-10-14T00:57:35Z",
                          "id": "CR04589531176955281409",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": "2026-11-03T00:48:22Z",
                          "paid_by": null,
                          "platform": "google",
                          "platform_specific": {
                            "google": {
                              "days_shown": 21,
                              "is_synthetic": null,
                              "product_category": null,
                              "regions": [],
                              "targeting": null,
                              "topic": null
                            }
                          },
                          "publisher_platforms": [],
                          "reach": null,
                          "spend": null,
                          "type": "text",
                          "unknown_fields": [
                            "country_codes",
                            "languages",
                            "platform_specific.google.regions"
                          ],
                          "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001/creative/CR04589531176955281409"
                        },
                        {
                          "advertiser": {
                            "avatar_url": null,
                            "display_name": "lululemon athletica canada inc.",
                            "id": "AR01614014350098432001",
                            "is_verified": true,
                            "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001",
                            "username": null
                          },
                          "approximate_fields": [
                            "creatives"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": null,
                              "cta_text": null,
                              "link_description": null,
                              "link_url": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": null,
                                  "height": null,
                                  "thumbnail_url": null,
                                  "type": "image",
                                  "url": "https://tpc.googlesyndication.com/archive/simgad/8703432262747982451",
                                  "width": null
                                }
                              ],
                              "title": null
                            }
                          ],
                          "first_shown_at": "2024-08-27T09:13:20Z",
                          "id": "CR10993845259498160129",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": "2026-11-03T00:45:16Z",
                          "paid_by": null,
                          "platform": "google",
                          "platform_specific": {
                            "google": {
                              "days_shown": 485,
                              "is_synthetic": null,
                              "product_category": null,
                              "regions": [],
                              "targeting": null,
                              "topic": null
                            }
                          },
                          "publisher_platforms": [],
                          "reach": null,
                          "spend": null,
                          "type": "text",
                          "unknown_fields": [
                            "country_codes",
                            "languages",
                            "platform_specific.google.regions"
                          ],
                          "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001/creative/CR10993845259498160129"
                        },
                        {
                          "advertiser": {
                            "avatar_url": null,
                            "display_name": "lululemon athletica canada inc.",
                            "id": "AR01614014350098432001",
                            "is_verified": true,
                            "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001",
                            "username": null
                          },
                          "approximate_fields": [],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [],
                          "first_shown_at": "2026-08-11T21:42:51Z",
                          "id": "CR06360865746699943937",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": "2026-11-03T00:37:13Z",
                          "paid_by": null,
                          "platform": "google",
                          "platform_specific": {
                            "google": {
                              "days_shown": 84,
                              "is_synthetic": null,
                              "product_category": null,
                              "regions": [],
                              "targeting": null,
                              "topic": null
                            }
                          },
                          "publisher_platforms": [],
                          "reach": null,
                          "spend": null,
                          "type": "image",
                          "unknown_fields": [
                            "country_codes",
                            "creatives",
                            "languages"
                          ],
                          "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001/creative/CR06360865746699943937"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "google",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 278,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "AR01614014350098432001",
                          "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/GoogleAdsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Advertiser's ads by format, service and date",
        "tags": [
          "Google Ads Transparency Center"
        ],
        "x-socialtap-endpoint": "google.ads",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "free_filtered_pages": true,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "last shown, most recent first",
          "orders": {
            "newest": "last shown, most recent first",
            "oldest": "last shown, least recent first (topic=political)",
            "popular": "most impressions first (topic=political)",
            "spend": "most spent first (topic=political)"
          },
          "page_max": 40,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "ad",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/google/advertiser": {
      "get": {
        "description": "Returns one Google Ads Transparency Center advertiser by its ID or page link: name, legal name, country, verification and how many ads it has shown. The ad count is Google's range, overall or in one country, with when an ad was last shown. An election advertiser adds its election ad count, the countries it is verified for and its registrations with election regulators, such as a US FEC committee ID.\n\nReturns `{data, meta}`: `data` is a `Profile` object (Google calls it a advertiser) (the shared schema, the same on every platform). Null means unknown.\n\nIn Google's words: `metrics.post_count` is ads.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/google/advertiser/ (Markdown: https://socialtap.dev/docs/reference/google/advertiser/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/google/advertiser/index.md)",
          "url": "https://socialtap.dev/docs/reference/google/advertiser/"
        },
        "operationId": "google.advertiser.get",
        "parameters": [
          {
            "description": "The advertiser: its Ads Transparency Center ID (AR…) or its page link (adstransparency.google.com/advertiser/AR…), in any case.",
            "example": "https://adstransparency.google.com/advertiser/AR01614014350098432001?region=US",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The advertiser: its Ads Transparency Center ID (AR…) or its page link (adstransparency.google.com/advertiser/AR…), in any case.",
              "examples": [
                "AR01614014350098432001"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Count only the ads shown in this country. Every country when omitted.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Count only the ads shown in this country. Every country when omitted.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "metrics.post_count"
                        ],
                        "avatar_url": null,
                        "banner_url": null,
                        "bio": null,
                        "category": null,
                        "country_code": "CA",
                        "created_at": null,
                        "display_name": "lululemon athletica canada inc.",
                        "external_links": [],
                        "id": "AR01614014350098432001",
                        "is_private": null,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": null,
                          "following_count": null,
                          "post_count": 10000,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "google",
                        "platform_specific": {
                          "google": {
                            "ads": {
                              "lower_bound": 10000,
                              "upper_bound": 20000
                            },
                            "election": null,
                            "is_election_advertiser": false,
                            "last_shown_at": "2026-11-03T00:48:22Z",
                            "legal_name": "lululemon athletica canada inc."
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [
                          "external_links"
                        ],
                        "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001",
                        "username": null
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "google",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 220,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "AR01614014350098432001",
                          "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/GoogleAdvertiserResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Identity, verification and ad count",
        "tags": [
          "Google Ads Transparency Center"
        ],
        "x-socialtap-endpoint": "google.advertiser",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/google/search_ads": {
      "get": {
        "description": "Returns the ads that lead to a website, from every advertiser that runs them, in Google's Ads Transparency Center, by domain or any link to it. Each ad has its advertiser (ID, name and verification), format, image and first and last day shown, across Google Search, YouTube, Maps, Play and Shopping. Filter by country, format, service and dates, or list only election ads, which add their countries and Google's impressions and spend ranges and sort by impressions or spend. Ads come most recently shown first.\n\nReturns `{data, page, meta}`: `data` holds up to 40 `Ad` items (the shared schema, the same on every platform), last shown, most recent first with sort=newest (the default), last shown, least recent first (topic=political) with sort=oldest, most impressions first (topic=political) with sort=popular, most spent first (topic=political) with sort=spend. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/google/search_ads/ (Markdown: https://socialtap.dev/docs/reference/google/search_ads/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/google/search_ads/index.md)",
          "url": "https://socialtap.dev/docs/reference/google/search_ads/"
        },
        "operationId": "google.search_ads.list",
        "parameters": [
          {
            "description": "The website: its domain (lululemon.com), any link to it (https://www.lululemon.com/en-us/…), or an Ads Transparency Center domain search link (adstransparency.google.com/?domain=…). Google files ads under the registrable domain, so www. and subdomains search it (shop.lululemon.com is lululemon.com).",
            "example": "lululemon.com",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "The website: its domain (lululemon.com), any link to it (https://www.lululemon.com/en-us/…), or an Ads Transparency Center domain search link (adstransparency.google.com/?domain=…). Google files ads under the registrable domain, so www. and subdomains search it (shop.lululemon.com is lululemon.com).",
              "examples": [
                "lululemon.com"
              ],
              "format": "domain",
              "maxLength": 500,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only ads shown in this country. All countries when omitted; required with topic=political.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only ads shown in this country. All countries when omitted; required with topic=political.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "political: only the election ads that lead to the website (the center's Political ads view), with their impressions and spend; needs country. Default: all.",
            "example": "",
            "in": "query",
            "name": "topic",
            "schema": {
              "default": "all",
              "description": "political: only the election ads that lead to the website (the center's Political ads view), with their impressions and spend; needs country. Default: all.",
              "enum": [
                "all",
                "political"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only ads of this format. All formats when omitted.",
            "example": "",
            "in": "query",
            "name": "format",
            "schema": {
              "description": "Only ads of this format. All formats when omitted.",
              "enum": [
                "text",
                "image",
                "video"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only ads shown on this Google service. All services when omitted.",
            "example": "",
            "in": "query",
            "name": "service",
            "schema": {
              "description": "Only ads shown on this Google service. All services when omitted.",
              "enum": [
                "google_search",
                "google_maps",
                "google_play",
                "google_shopping",
                "youtube"
              ],
              "type": "string"
            }
          },
          {
            "description": "Order of the results. newest: most recently shown first (the center's order). With topic=political also oldest (least recently shown first), popular (most impressions first) and spend (most spent first).",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "newest",
              "description": "Order of the results. newest: most recently shown first (the center's order). With topic=political also oldest (least recently shown first), popular (most impressions first) and spend (most spent first).",
              "enum": [
                "newest",
                "oldest",
                "popular",
                "spend"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Ads count when they were shown during the window: an ad last shown (last_shown_at) before since is left out.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Ads count when they were shown during the window: an ad last shown (last_shown_at) before since is left out.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Ads count when they were shown during the window: an ad first shown (first_shown_at) at or after until is left out.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Ads count when they were shown during the window: an ad first shown (first_shown_at) at or after until is left out.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 40,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 40,
              "maximum": 40,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "advertiser": {
                            "avatar_url": null,
                            "display_name": "lululemon athletica canada inc.",
                            "id": "AR01614014350098432001",
                            "is_verified": true,
                            "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001",
                            "username": null
                          },
                          "approximate_fields": [
                            "creatives"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": null,
                              "cta_text": null,
                              "link_description": null,
                              "link_url": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": null,
                                  "height": null,
                                  "thumbnail_url": null,
                                  "type": "image",
                                  "url": "https://tpc.googlesyndication.com/archive/simgad/989267650108216441",
                                  "width": null
                                }
                              ],
                              "title": null
                            }
                          ],
                          "first_shown_at": "2026-10-16T07:13:50Z",
                          "id": "CR01602111080165801985",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": "2026-11-03T01:13:20Z",
                          "paid_by": null,
                          "platform": "google",
                          "platform_specific": {
                            "google": {
                              "days_shown": 18,
                              "is_synthetic": null,
                              "product_category": null,
                              "regions": [],
                              "targeting": null,
                              "topic": null
                            }
                          },
                          "publisher_platforms": [],
                          "reach": null,
                          "spend": null,
                          "type": "text",
                          "unknown_fields": [
                            "country_codes",
                            "languages",
                            "platform_specific.google.regions"
                          ],
                          "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001/creative/CR01602111080165801985"
                        },
                        {
                          "advertiser": {
                            "avatar_url": null,
                            "display_name": "lululemon athletica canada inc.",
                            "id": "AR01614014350098432001",
                            "is_verified": true,
                            "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001",
                            "username": null
                          },
                          "approximate_fields": [
                            "creatives"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": null,
                              "cta_text": null,
                              "link_description": null,
                              "link_url": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": null,
                                  "height": null,
                                  "thumbnail_url": null,
                                  "type": "image",
                                  "url": "https://tpc.googlesyndication.com/archive/simgad/6465019125132301667",
                                  "width": null
                                }
                              ],
                              "title": null
                            }
                          ],
                          "first_shown_at": "2026-10-14T00:57:35Z",
                          "id": "CR04589531176955281409",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": "2026-11-03T00:48:22Z",
                          "paid_by": null,
                          "platform": "google",
                          "platform_specific": {
                            "google": {
                              "days_shown": 21,
                              "is_synthetic": null,
                              "product_category": null,
                              "regions": [],
                              "targeting": null,
                              "topic": null
                            }
                          },
                          "publisher_platforms": [],
                          "reach": null,
                          "spend": null,
                          "type": "text",
                          "unknown_fields": [
                            "country_codes",
                            "languages",
                            "platform_specific.google.regions"
                          ],
                          "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001/creative/CR04589531176955281409"
                        },
                        {
                          "advertiser": {
                            "avatar_url": null,
                            "display_name": "lululemon athletica canada inc.",
                            "id": "AR01614014350098432001",
                            "is_verified": true,
                            "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001",
                            "username": null
                          },
                          "approximate_fields": [
                            "creatives"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": null,
                              "cta_text": null,
                              "link_description": null,
                              "link_url": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": null,
                                  "height": null,
                                  "thumbnail_url": null,
                                  "type": "image",
                                  "url": "https://tpc.googlesyndication.com/archive/simgad/8703432262747982451",
                                  "width": null
                                }
                              ],
                              "title": null
                            }
                          ],
                          "first_shown_at": "2024-08-27T09:13:20Z",
                          "id": "CR10993845259498160129",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": "2026-11-03T00:45:16Z",
                          "paid_by": null,
                          "platform": "google",
                          "platform_specific": {
                            "google": {
                              "days_shown": 485,
                              "is_synthetic": null,
                              "product_category": null,
                              "regions": [],
                              "targeting": null,
                              "topic": null
                            }
                          },
                          "publisher_platforms": [],
                          "reach": null,
                          "spend": null,
                          "type": "text",
                          "unknown_fields": [
                            "country_codes",
                            "languages",
                            "platform_specific.google.regions"
                          ],
                          "url": "https://adstransparency.google.com/advertiser/AR01614014350098432001/creative/CR10993845259498160129"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "google",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 281,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/GoogleSearch_adsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Ads that lead to a website, from any advertiser",
        "tags": [
          "Google Ads Transparency Center"
        ],
        "x-socialtap-endpoint": "google.search_ads",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "free_filtered_pages": true,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "last shown, most recent first",
          "orders": {
            "newest": "last shown, most recent first",
            "oldest": "last shown, least recent first (topic=political)",
            "popular": "most impressions first (topic=political)",
            "spend": "most spent first (topic=political)"
          },
          "page_max": 40,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "ad",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/google/search_advertisers": {
      "get": {
        "description": "Returns the Google Ads Transparency Center advertisers whose name matches a query, every match rather than the search box's first ten. Each advertiser has its AR ID (the one its ads and page use), name, country, verification and ad count as Google's range. Filter to advertisers whose ads ran in one country, with their counts there, and sort by Google's order or most ads first.\n\nReturns `{data, page, meta}`: `data` holds up to 100 `Profile` items (Google calls it a advertiser) (the shared schema, the same on every platform), Google's order, as the center's search box lists the matches with sort=relevance (the default), most ads first, by the center's ad counts (the upper bound, then the lower), Google's order among equals with sort=popular. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Google's words: `metrics.post_count` is ads.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/google/search_advertisers/ (Markdown: https://socialtap.dev/docs/reference/google/search_advertisers/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/google/search_advertisers/index.md)",
          "url": "https://socialtap.dev/docs/reference/google/search_advertisers/"
        },
        "operationId": "google.search_advertisers.list",
        "parameters": [
          {
            "description": "An advertiser's name, or a part of it, as typed into the Ads Transparency Center's search box, in any language (nike, lululemon athletica, トヨタ). Case and punctuation do not matter.",
            "example": "lululemon",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "An advertiser's name, or a part of it, as typed into the Ads Transparency Center's search box, in any language (nike, lululemon athletica, トヨタ). Case and punctuation do not matter.",
              "examples": [
                "lululemon"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only advertisers whose ads were shown in this country, with their ad counts there. Every country when omitted.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only advertisers whose ads were shown in this country, with their ad counts there. Every country when omitted.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Order of the results. relevance (default): Google's order, as the center's search box lists them. popular: most ads first, by Google's ad counts.",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "relevance",
              "description": "Order of the results. relevance (default): Google's order, as the center's search box lists them. popular: most ads first, by Google's ad counts.",
              "enum": [
                "relevance",
                "popular"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 100,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "avatar_url": null,
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": "MX",
                          "created_at": null,
                          "display_name": "LULULEMON MEXICO",
                          "external_links": [],
                          "id": "AR02903092099014459393",
                          "is_private": null,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": 16,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "google",
                          "platform_specific": {
                            "google": {
                              "ads": {
                                "lower_bound": 16,
                                "upper_bound": 16
                              },
                              "election": null,
                              "is_election_advertiser": null,
                              "last_shown_at": null,
                              "legal_name": null
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links"
                          ],
                          "url": "https://adstransparency.google.com/advertiser/AR02903092099014459393",
                          "username": null
                        },
                        {
                          "approximate_fields": [
                            "metrics.post_count"
                          ],
                          "avatar_url": null,
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": "HK",
                          "created_at": null,
                          "display_name": "lululemon HK Limited",
                          "external_links": [],
                          "id": "AR01382517811867287553",
                          "is_private": null,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": 4000,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "google",
                          "platform_specific": {
                            "google": {
                              "ads": {
                                "lower_bound": 4000,
                                "upper_bound": 5000
                              },
                              "election": null,
                              "is_election_advertiser": null,
                              "last_shown_at": null,
                              "legal_name": null
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links"
                          ],
                          "url": "https://adstransparency.google.com/advertiser/AR01382517811867287553",
                          "username": null
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": null,
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": "QA",
                          "created_at": null,
                          "display_name": "LULULEMON ATHLETICA TRADING",
                          "external_links": [],
                          "id": "AR06362141867382931457",
                          "is_private": null,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": 55,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "google",
                          "platform_specific": {
                            "google": {
                              "ads": {
                                "lower_bound": 55,
                                "upper_bound": 55
                              },
                              "election": null,
                              "is_election_advertiser": null,
                              "last_shown_at": null,
                              "legal_name": null
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links"
                          ],
                          "url": "https://adstransparency.google.com/advertiser/AR06362141867382931457",
                          "username": null
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "google",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 234,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "end"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/GoogleSearch_advertisersResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Advertisers by name, with IDs and ad counts",
        "tags": [
          "Google Ads Transparency Center"
        ],
        "x-socialtap-endpoint": "google.search_advertisers",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Google's order, as the center's search box lists the matches",
          "orders": {
            "popular": "most ads first, by the center's ad counts (the upper bound, then the lower), Google's order among equals",
            "relevance": "Google's order, as the center's search box lists the matches"
          },
          "page_max": 100,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/google/search_suggestions": {
      "get": {
        "description": "Returns what the Google Ads Transparency Center search box suggests for a query, in its order: matching advertisers, then websites with ads. Each advertiser has its AR ID, name, country, verification badge and ad count as Google's range, and each website its bare domain, ready for the Google Ads Transparency Center Ads by Website API. Filter to one country, and page past what the box shows.\n\nReturns `{data, page, meta}`: `data` holds up to 20 `Suggestion` items (the shared schema, the same on every platform), the center's search box order: on each page its advertisers, then its websites. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/google/search_suggestions/ (Markdown: https://socialtap.dev/docs/reference/google/search_suggestions/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/google/search_suggestions/index.md)",
          "url": "https://socialtap.dev/docs/reference/google/search_suggestions/"
        },
        "operationId": "google.search_suggestions.list",
        "parameters": [
          {
            "description": "What to search for, as typed into the Ads Transparency Center's search box: an advertiser's name or a website's domain, or a part of either, in any language (lululemon, nike.com, トヨタ). Case does not matter.",
            "example": "Lululemon",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to search for, as typed into the Ads Transparency Center's search box: an advertiser's name or a website's domain, or a part of either, in any language (lululemon, nike.com, トヨタ). Case does not matter.",
              "examples": [
                "lululemon"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only advertisers and websites whose ads were shown in this country, with the advertisers' ad counts there. Every country when omitted.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only advertisers and websites whose ads were shown in this country, with the advertisers' ad counts there. Every country when omitted.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 20,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "hashtag": null,
                          "platform": "google",
                          "platform_specific": {
                            "google": {
                              "ads": {
                                "lower_bound": 16,
                                "upper_bound": 16
                              },
                              "country_code": "MX"
                            }
                          },
                          "position": 0,
                          "profile": {
                            "avatar_url": null,
                            "display_name": "LULULEMON MEXICO",
                            "id": "AR02903092099014459393",
                            "is_verified": true,
                            "url": "https://adstransparency.google.com/advertiser/AR02903092099014459393",
                            "username": null
                          },
                          "text": "LULULEMON MEXICO",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://adstransparency.google.com/advertiser/AR02903092099014459393"
                        },
                        {
                          "approximate_fields": [],
                          "hashtag": null,
                          "platform": "google",
                          "platform_specific": {
                            "google": {
                              "ads": {
                                "lower_bound": 4000,
                                "upper_bound": 5000
                              },
                              "country_code": "HK"
                            }
                          },
                          "position": 1,
                          "profile": {
                            "avatar_url": null,
                            "display_name": "lululemon HK Limited",
                            "id": "AR01382517811867287553",
                            "is_verified": true,
                            "url": "https://adstransparency.google.com/advertiser/AR01382517811867287553",
                            "username": null
                          },
                          "text": "lululemon HK Limited",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://adstransparency.google.com/advertiser/AR01382517811867287553"
                        },
                        {
                          "approximate_fields": [],
                          "hashtag": null,
                          "platform": "google",
                          "platform_specific": {
                            "google": {
                              "ads": {
                                "lower_bound": 55,
                                "upper_bound": 55
                              },
                              "country_code": "QA"
                            }
                          },
                          "position": 2,
                          "profile": {
                            "avatar_url": null,
                            "display_name": "LULULEMON ATHLETICA TRADING",
                            "id": "AR06362141867382931457",
                            "is_verified": true,
                            "url": "https://adstransparency.google.com/advertiser/AR06362141867382931457",
                            "username": null
                          },
                          "text": "LULULEMON ATHLETICA TRADING",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://adstransparency.google.com/advertiser/AR06362141867382931457"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "google",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 197,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/GoogleSearch_suggestionsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Advertisers and websites suggested for a query",
        "tags": [
          "Google Ads Transparency Center"
        ],
        "x-socialtap-endpoint": "google.search_suggestions",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the center's search box order: on each page its advertisers, then its websites",
          "page_max": 20,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "suggestion",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/comment": {
      "get": {
        "description": "Returns one public top-level comment on an Instagram post, reel or carousel, from its link or the post's link and comment_id. You get its text, exact like count, posting time, the GIF when it is one, whether the post's author wrote it, and the commenter's username, ID, picture and verified badge.\n\nReturns `{data, meta}`: `data` is a `Comment` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/comment/ (Markdown: https://socialtap.dev/docs/reference/instagram/comment/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/comment/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/comment/"
        },
        "operationId": "instagram.comment.get",
        "parameters": [
          {
            "description": "The comment's permalink (instagram.com/p/<code>/c/<comment ID>/, also on /reel/, /reels/, /tv/ and /<username>/p/ links, m.instagram.com and instagr.am, and a reply's /c/<comment ID>/r/<reply ID>/), or the post the comment is on: a post, reel or carousel link, a share link (instagram.com/share/…), a raw shortcode or a numeric media ID. Tracking params are ignored.",
            "example": "https://www.instagram.com/natgeo/p/DeuOR-CjKE9/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The comment's permalink (instagram.com/p/<code>/c/<comment ID>/, also on /reel/, /reels/, /tv/ and /<username>/p/ links, m.instagram.com and instagr.am, and a reply's /c/<comment ID>/r/<reply ID>/), or the post the comment is on: a post, reel or carousel link, a share link (instagram.com/share/…), a raw shortcode or a numeric media ID. Tracking params are ignored.",
              "examples": [
                "https://www.instagram.com/p/DeuOR-CjKE9/c/18172542484466705/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "ID of the comment (the id of a comment from the comments endpoint). Required unless url is a comment's permalink; when both are given they must name the same comment.",
            "example": "18201877798382683",
            "in": "query",
            "name": "comment_id",
            "schema": {
              "description": "ID of the comment (the id of a comment from the comments endpoint). Required unless url is a comment's permalink; when both are given they must name the same comment.",
              "examples": [
                "18172542484466705"
              ],
              "maxLength": 32,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/487214600_1013796433961568_4617588958569444737_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=111&ig_cache_key=GAhOCh1gIlLgCpoDAIE1TFqx_BRAbkULAAAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCR…",
                          "display_name": null,
                          "id": "2736561256",
                          "is_verified": true,
                          "url": "https://www.instagram.com/tropiclifepr/",
                          "username": "tropiclifepr"
                        },
                        "edited_at": null,
                        "id": "18201877798382683",
                        "is_by_post_author": false,
                        "is_edited": null,
                        "is_liked_by_author": null,
                        "is_pinned": null,
                        "metrics": {
                          "like_count": 1,
                          "reply_count": null
                        },
                        "parent_id": null,
                        "platform": "instagram",
                        "platform_specific": {
                          "instagram": {
                            "gif_url": null
                          }
                        },
                        "post_id": "DeuOR-CjKE9",
                        "published_at": "2026-10-28T13:22:42Z",
                        "text": "Puerto Rico 🇵🇷 🇵🇷 🇵🇷 🇵🇷",
                        "unknown_fields": [],
                        "url": "https://www.instagram.com/p/DeuOR-CjKE9/c/18201877798382683/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 629,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "18201877798382683",
                          "url": "https://www.instagram.com/p/DeuOR-CjKE9/c/18201877798382683/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramCommentResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Text, exact likes and author, from its link",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.comment",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/comments": {
      "get": {
        "description": "Returns the top-level comments on a public Instagram post, reel or carousel, newest first, a page at a time, from its link or shortcode. Each has its text, posting time, like count, whether the post's author wrote it, and the commenter's username, ID, picture and verified badge.\n\nReturns `{data, page, meta}`: `data` holds up to 24 `Comment` items (the shared schema, the same on every platform), newest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/comments/ (Markdown: https://socialtap.dev/docs/reference/instagram/comments/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/comments/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/comments/"
        },
        "operationId": "instagram.comments.list",
        "parameters": [
          {
            "description": "Instagram post, reel or carousel URL (instagram.com/p/…, /reel/…, /reels/…, /tv/…, /<username>/p/…, m.instagram.com, instagr.am, instagram.com/share/… links), a raw shortcode or a numeric media ID (4012207125530714429, or with its _<user ID> suffix). Tracking params and img_index are ignored.",
            "example": "https://www.instagram.com/natgeo/p/DeuOR-CjKE9/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Instagram post, reel or carousel URL (instagram.com/p/…, /reel/…, /reels/…, /tv/…, /<username>/p/…, m.instagram.com, instagr.am, instagram.com/share/… links), a raw shortcode or a numeric media ID (4012207125530714429, or with its _<user ID> suffix). Tracking params and img_index are ignored.",
              "examples": [
                "https://www.instagram.com/p/DeuOR-CjKE9/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 24,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 24,
              "maximum": 24,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/659026685_17991098504947880_2935590941239143385_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid…",
                            "display_name": null,
                            "id": "58470243879",
                            "is_verified": false,
                            "url": "https://www.instagram.com/dovistravels/",
                            "username": "dovistravels"
                          },
                          "edited_at": null,
                          "id": "18172542484466705",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 0,
                            "reply_count": null
                          },
                          "parent_id": null,
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "gif_url": null
                            }
                          },
                          "post_id": "DeuOR-CjKE9",
                          "published_at": "2026-11-02T11:55:16Z",
                          "text": "So many incredible destinations 👏",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/p/DeuOR-CjKE9/c/18172542484466705/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-19/881214533_18154592410588913_31986000253115770_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_gid=S…",
                            "display_name": null,
                            "id": "17581364912",
                            "is_verified": false,
                            "url": "https://www.instagram.com/monique.meier1506/",
                            "username": "monique.meier1506"
                          },
                          "edited_at": null,
                          "id": "18137851468639974",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 0,
                            "reply_count": null
                          },
                          "parent_id": null,
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "gif_url": null
                            }
                          },
                          "post_id": "DeuOR-CjKE9",
                          "published_at": "2026-11-02T07:10:11Z",
                          "text": "😍😍😍",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/p/DeuOR-CjKE9/c/18137851468639974/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/642971158_18042956444535313_7384894640051603948_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=104&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid…",
                            "display_name": null,
                            "id": "46021735312",
                            "is_verified": false,
                            "url": "https://www.instagram.com/penguin.8656465/",
                            "username": "penguin.8656465"
                          },
                          "edited_at": null,
                          "id": "18036657161665725",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 0,
                            "reply_count": null
                          },
                          "parent_id": null,
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "gif_url": null
                            }
                          },
                          "post_id": "DeuOR-CjKE9",
                          "published_at": "2026-11-02T01:39:04Z",
                          "text": "Such stunning destinations! That scenery is truly breathtaking.",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/p/DeuOR-CjKE9/c/18036657161665725/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 656,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "DeuOR-CjKE9",
                          "url": "https://www.instagram.com/p/DeuOR-CjKE9/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramCommentsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "On a post or reel, newest first, with likes",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.comments",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "page_max": 24,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/embed": {
      "get": {
        "description": "Returns Instagram's own embed code for a public post, reel or profile, from its link. You get the HTML snippet, with or without the caption and the embed.js tag, at the width you choose, plus the iframe link it loads, the caption or profile title, the author and the thumbnail with its size.\n\nReturns `{data, meta}`: `data` is a `Embed` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/embed/ (Markdown: https://socialtap.dev/docs/reference/instagram/embed/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/embed/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/embed/"
        },
        "operationId": "instagram.embed.get",
        "parameters": [
          {
            "description": "Instagram post, reel or profile link (instagram.com/p/…, /reel/…, /reels/…, /tv/…, /<username>/p/…, share links, m.instagram.com, instagr.am, instagram.com/<username>/) or a post's raw shortcode. A username needs its profile link: a bare string is read as a shortcode.",
            "example": "https://www.instagram.com/p/DeuOR-CjKE9/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Instagram post, reel or profile link (instagram.com/p/…, /reel/…, /reels/…, /tv/…, /<username>/p/…, share links, m.instagram.com, instagr.am, instagram.com/<username>/) or a post's raw shortcode. A username needs its profile link: a bare string is read as a shortcode.",
              "examples": [
                "https://www.instagram.com/p/DeuOR-CjKE9/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Widest the embed may be laid out, in pixels (default and most: 658; a wider value is laid out at 658). Instagram's embeds are responsive below it.",
            "example": "",
            "in": "query",
            "name": "max_width",
            "schema": {
              "description": "Widest the embed may be laid out, in pixels (default and most: 658; a wider value is laid out at 658). Instagram's embeds are responsive below it.",
              "format": "int64",
              "minimum": 320,
              "type": "integer"
            }
          },
          {
            "description": "Embed a post without its caption (Instagram's hidecaption). Profiles have none: ignored for a profile link.",
            "example": "",
            "in": "query",
            "name": "hide_caption",
            "schema": {
              "description": "Embed a post without its caption (Instagram's hidecaption). Profiles have none: ignored for a profile link.",
              "type": "boolean"
            }
          },
          {
            "description": "Leave Instagram's embed.js script tag out of html, for a page that loads it once itself (then call window.instgrm.Embeds.process() after inserting the markup).",
            "example": "",
            "in": "query",
            "name": "omit_script",
            "schema": {
              "description": "Leave Instagram's embed.js script tag out of html, for a page that loads it once itself (then call window.instgrm.Embeds.process() after inserting the markup).",
              "type": "boolean"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "author": {
                          "avatar_url": null,
                          "display_name": "National Geographic",
                          "id": "787132",
                          "is_verified": null,
                          "url": "https://www.instagram.com/natgeo/",
                          "username": "natgeo"
                        },
                        "embed_url": "https://www.instagram.com/p/DeuOR-CjKE9/embed/captioned/",
                        "height": null,
                        "html": "<blockquote class=\"instagram-media\" data-instgrm-captioned data-instgrm-permalink=\"https://www.instagram.com/p/DeuOR-CjKE9/?utm_source=ig_embed&amp;utm_campaign=loading\" data-instgrm-version=\"14\" style=\" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,…",
                        "id": "DeuOR-CjKE9",
                        "platform": "instagram",
                        "platform_specific": {},
                        "thumbnail_height": 800,
                        "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/858921974_18710195065019133_277441153414192961_n.jpg?stp=dst-jpg_e35_p640x640_sh2.08_tt6&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_cat=109&_nc_oc=SCRUBBED&_nc_ohc=SCRUBBED&_nc_gid=SCRUBBED&edm=SCRUBBED&ccb=SCRUBBED&oh=SCRU…",
                        "thumbnail_width": 640,
                        "title": "Some of the best reasons to travel in 2027 are far from the usual destinations. 🌎\n\nNational Geographic’s picks for Best of the World 2027 are here and features 25 destinations across six continents. \n\nWhether you're drawn to places steeped in history or the thrill of exploring th…",
                        "type": "post",
                        "url": "https://www.instagram.com/p/DeuOR-CjKE9/",
                        "width": 658
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 254,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "DeuOR-CjKE9",
                          "url": "https://www.instagram.com/p/DeuOR-CjKE9/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramEmbedResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Embed code for a post, reel or profile",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.embed",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "embed",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/engagement": {
      "get": {
        "description": "Returns a public Instagram account's engagement rate over its latest posts, with its profile and those posts, from a username, link or user ID. The rate is per follower and per view, as mean, median and spread. You also get likes and comments per post, views per reel, comment-to-like ratio, posting cadence, the mix of reels, photos and carousels, and each post against the account's typical one.\n\nReturns `{data, meta}`: `data` is a `Engagement` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/engagement/ (Markdown: https://socialtap.dev/docs/reference/instagram/engagement/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/engagement/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/engagement/"
        },
        "operationId": "instagram.engagement.get",
        "parameters": [
          {
            "description": "Instagram username with or without the @ (natgeo, @natgeo), a numeric user ID (787132), or a profile link (instagram.com/natgeo, with or without a tab such as /reels/ or /tagged/, m.instagram.com, instagr.am, instagram.com/_u/natgeo, with any query such as ?igsh=…). Usernames are case-insensitive. A bare number is a user ID; a number no account has as its ID is looked up as a username, and @ before digits (@2020) always means the username.",
            "example": "nasa",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Instagram username with or without the @ (natgeo, @natgeo), a numeric user ID (787132), or a profile link (instagram.com/natgeo, with or without a tab such as /reels/ or /tagged/, m.instagram.com, instagr.am, instagram.com/_u/natgeo, with any query such as ?igsh=…). Usernames are case-insensitive. A bare number is a user ID; a number no account has as its ID is looked up as a username, and @ before digits (@2020) always means the username.",
              "examples": [
                "natgeo"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "bottom_post_id": "DfCo97ZlL5F",
                        "id": "528817151",
                        "metrics": {
                          "comment_to_like_ratio": 0.002639,
                          "comments_per_post": 1530.67,
                          "counted_post_count": 6,
                          "engagement_rate": 0.00557,
                          "engagement_rate_stddev": 0.004258,
                          "formats": [
                            {
                              "counted_post_count": 5,
                              "engagement_rate": 0.003876,
                              "interactions_per_post": 404732.8,
                              "type": "image",
                              "views_per_post": null
                            },
                            {
                              "counted_post_count": 1,
                              "engagement_rate": 0.014039,
                              "interactions_per_post": 1465958,
                              "type": "carousel",
                              "views_per_post": null
                            }
                          ],
                          "interactions_per_post": 581603.67,
                          "likes_per_post": 580073,
                          "median_engagement_rate": 0.004124,
                          "median_views_per_post": null,
                          "posts_per_week": 7.15,
                          "quotes_per_post": null,
                          "rated_post_count": 6,
                          "reposts_per_post": null,
                          "sampled_post_count": 12,
                          "saves_per_post": null,
                          "shares_per_post": null,
                          "view_engagement_rate": null,
                          "views_per_post": null
                        },
                        "newest_post_at": "2026-10-30T19:59:43Z",
                        "oldest_post_at": "2026-10-25T22:30:00Z",
                        "platform": "instagram",
                        "platform_specific": {},
                        "posts": [
                          {
                            "engagement_rate": 0.007422,
                            "engagement_vs_median": 1.8,
                            "is_counted": false,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/29090066_159271188110124_1152068159029641216_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ig_cache_key=GBLhuwEsG5c225AAAAAAAADj9-wPbkULAAAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBE…",
                                "display_name": "NASA",
                                "id": "528817151",
                                "is_verified": true,
                                "url": "https://www.instagram.com/nasa/",
                                "username": "nasa"
                              },
                              "coauthors": [
                                {
                                  "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.2885-19/93880139_247576663101568_4560165171292536832_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ss=7b68…",
                                  "display_name": "NASA Solar System Exploration",
                                  "id": "1611722079",
                                  "is_verified": true,
                                  "url": "https://www.instagram.com/nasasolarsystem/",
                                  "username": "nasasolarsystem"
                                },
                                {
                                  "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/670016304_18577283653042671_4689932669633757619_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=S…",
                                  "display_name": "NASA Artemis",
                                  "id": "1104426670",
                                  "is_verified": true,
                                  "url": "https://www.instagram.com/nasaartemis/",
                                  "username": "nasaartemis"
                                }
                              ],
                              "duration_ms": 43767,
                              "hashtags": [
                                "NASA",
                                "ArtemisII",
                                "Artemis"
                              ],
                              "id": "DeTUk4sDSp-",
                              "is_nsfw": null,
                              "is_pinned": true,
                              "is_sponsored": false,
                              "language": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": 43767,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": 1908,
                                  "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/842191580_18656578867049152_4200499629839780998_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=111&ig_cache_key=NDAwNDYzNDk4OTM2MjQ4OTk4MjE4NjU2NTc4ODYxMDQ5MTUy.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                                  "type": "video",
                                  "url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t2/f2/m86/AQNUvreb47JFAC3mKM7kF_weYHzhiVF-MfERm99CfyBTok0ezeRdbVW8cH5NXn4mxO8gVi6j1GQ2RU9i4ByvKCLVPHdDruUpsCKYDQI.mp4?_nc_cat=105&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                                  "width": 1074
                                }
                              ],
                              "mentions": [
                                "nasaartemis",
                                "nasasolarsystem"
                              ],
                              "metrics": {
                                "comment_count": 7677,
                                "like_count": 767368,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": null,
                                "share_count": null,
                                "view_count": 11243231
                              },
                              "platform": "instagram",
                              "platform_specific": {
                                "instagram": {
                                  "is_ai_generated": false,
                                  "link": null,
                                  "location": null
                                }
                              },
                              "platform_type": "reel",
                              "published_at": "2026-10-10T15:15:02Z",
                              "text": "POV: you're watching the Earth set\n\nWe just released hundreds of new images and hours of new audio from our Artemis II mission around the Moon this spring. Check out our link in bio for the Artemis II Preliminary Lunar Science Report.\n\n#NASA #ArtemisII #Artemis",
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/842191580_18656578867049152_4200499629839780998_n.jpg?stp=c0.417.1074.1074a_dst-jpg_e15_tt6&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.cdninstagra…",
                              "title": null,
                              "type": "video",
                              "unknown_fields": [],
                              "url": "https://www.instagram.com/reel/DeTUk4sDSp-/"
                            },
                            "view_engagement_rate": 0.068934,
                            "views_vs_median": null
                          },
                          {
                            "engagement_rate": 0.002856,
                            "engagement_vs_median": 0.69,
                            "is_counted": false,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/432029380_939863124412845_4074172309041694202_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ss=7b689…",
                                "display_name": "NASA Webb Telescope",
                                "id": "549313808",
                                "is_verified": true,
                                "url": "https://www.instagram.com/nasawebb/",
                                "username": "nasawebb"
                              },
                              "coauthors": [
                                {
                                  "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/437785305_1498177207718392_5285428334541669140_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=105&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ss=7b…",
                                  "display_name": "NASA Universe",
                                  "id": "65495240044",
                                  "is_verified": true,
                                  "url": "https://www.instagram.com/nasauniverse/",
                                  "username": "nasauniverse"
                                },
                                {
                                  "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/29090066_159271188110124_1152068159029641216_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ig_cache_key=GBLhuwEsG5c225AAAAAAAADj9-wPbkULAAAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBE…",
                                  "display_name": "NASA",
                                  "id": "528817151",
                                  "is_verified": true,
                                  "url": "https://www.instagram.com/nasa/",
                                  "username": "nasa"
                                }
                              ],
                              "duration_ms": null,
                              "hashtags": [],
                              "id": "DeJ28eTxo4s",
                              "is_nsfw": null,
                              "is_pinned": true,
                              "is_sponsored": false,
                              "language": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": 1872,
                                  "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/838879752_18633093571001809_7013098794556155636_n.jpg?stp=c64.0.1872.1872a_dst-jpg_e35_s1080x1080_sh2.08_tt6&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-a…",
                                  "type": "image",
                                  "url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/838879752_18633093571001809_7013098794556155636_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=109&ig_cache_key=NDAwMTk3MTM5NDExOTYzNDQ3Ng%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                                  "width": 2000
                                }
                              ],
                              "mentions": [
                                "NASAWebb",
                                "nasa",
                                "nasauniverse"
                              ],
                              "metrics": {
                                "comment_count": 1066,
                                "like_count": 297195,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": null,
                                "share_count": null,
                                "view_count": null
                              },
                              "platform": "instagram",
                              "platform_specific": {
                                "instagram": {
                                  "is_ai_generated": false,
                                  "link": null,
                                  "location": null
                                }
                              },
                              "platform_type": "post",
                              "published_at": "2026-10-06T13:10:11Z",
                              "text": "Brewing up new stars 🪄\n \n@NASAWebb’s unique view of the stellar nursery known as NGC 7129 reveals numerous stars formerly hidden in this cosmic cauldron. \n \nStars begin their life in cold, dense regions of dust and gas, hiding from view of most telescopes. Webb’s high degree of i…",
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/838879752_18633093571001809_7013098794556155636_n.jpg?stp=c64.0.1872.1872a_dst-jpg_e35_s1080x1080_sh2.08_tt6&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-a…",
                              "title": null,
                              "type": "image",
                              "unknown_fields": [],
                              "url": "https://www.instagram.com/p/DeJ28eTxo4s/"
                            },
                            "view_engagement_rate": null,
                            "views_vs_median": null
                          },
                          {
                            "engagement_rate": 0.013192,
                            "engagement_vs_median": 3.2,
                            "is_counted": false,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/29090066_159271188110124_1152068159029641216_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ig_cache_key=GBLhuwEsG5c225AAAAAAAADj9-wPbkULAAAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBE…",
                                "display_name": "NASA",
                                "id": "528817151",
                                "is_verified": true,
                                "url": "https://www.instagram.com/nasa/",
                                "username": "nasa"
                              },
                              "coauthors": [],
                              "duration_ms": null,
                              "hashtags": [
                                "NASA",
                                "Space",
                                "Stars"
                              ],
                              "id": "DeAYvsnn4la",
                              "is_nsfw": null,
                              "is_pinned": true,
                              "is_sponsored": false,
                              "language": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": 1350,
                                  "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/831222439_18653890615049152_5346150317938845760_n.jpg?stp=c0.135.1080.1080a_dst-jpg_e15_s1080x1080_tt6&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.…",
                                  "type": "image",
                                  "url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/831222439_18653890615049152_5346150317938845760_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=110&ig_cache_key=Mzk5OTMwNDc1ODAwMTk1MzE5OA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                                  "width": 1080
                                },
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": 1350,
                                  "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/830418338_18653890612049152_312587861543217627_n.jpg?stp=c0.135.1080.1080a_dst-jpg_e15_s1080x1080_tt6&_nc_cat=100&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.c…",
                                  "type": "image",
                                  "url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/830418338_18653890612049152_312587861543217627_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=100&ig_cache_key=Mzk5OTMwNDc1ODM0NjExNzEyOA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=2…",
                                  "width": 1080
                                },
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": 1350,
                                  "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/831354642_18653890627049152_4381034991606753149_n.jpg?stp=c0.135.1080.1080a_dst-jpg_e15_s1080x1080_tt6&_nc_cat=104&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.…",
                                  "type": "image",
                                  "url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/831354642_18653890627049152_4381034991606753149_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=104&ig_cache_key=Mzk5OTMwNDc2MDcwMzExNzQxOA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                                  "width": 1080
                                }
                              ],
                              "mentions": [
                                "NASAWebb"
                              ],
                              "metrics": {
                                "comment_count": 5627,
                                "like_count": 1371892,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": null,
                                "share_count": null,
                                "view_count": null
                              },
                              "platform": "instagram",
                              "platform_specific": {
                                "instagram": {
                                  "is_ai_generated": false,
                                  "link": null,
                                  "location": null
                                }
                              },
                              "platform_type": "post",
                              "published_at": "2026-10-02T20:52:45Z",
                              "text": "Swipe for countless stars\n\nSagittarius B2 is the most massive and most active star-forming region in the Milky Way. It produces half of the stars in our home galaxy’s core.\n\nThis image of Sagittarius B2 was taken by our @NASAWebb telescope.\n\n#NASA #Space #Stars",
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/831222439_18653890615049152_5346150317938845760_n.jpg?stp=c0.135.1080.1080a_dst-jpg_e15_s1080x1080_tt6&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.…",
                              "title": null,
                              "type": "carousel",
                              "unknown_fields": [],
                              "url": "https://www.instagram.com/p/DeAYvsnn4la/"
                            },
                            "view_engagement_rate": null,
                            "views_vs_median": null
                          }
                        ],
                        "profile": {
                          "approximate_fields": [],
                          "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/29090066_159271188110124_1152068159029641216_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ig_cache_key=GBLhuwEsG5c225AAAAAAAADj9-wPbkULAAAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBE…",
                          "banner_url": null,
                          "bio": "Making the seemingly impossible, possible. ✨",
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "NASA",
                          "external_links": [
                            {
                              "title": "NASA.gov Homepage",
                              "url": "https://www.nasa.gov"
                            },
                            {
                              "title": "MAX POWER",
                              "url": "https://www.nasa.gov/maxpower"
                            },
                            {
                              "title": "Roman Space Telescope Blog",
                              "url": "https://science.nasa.gov/blogs/roman/"
                            }
                          ],
                          "id": "528817151",
                          "is_private": false,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": 104419589,
                            "following_count": 90,
                            "post_count": 4986,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "account_type": null,
                              "fbid": "17841401474538262",
                              "is_highlights_shown": true,
                              "is_memorialized": false,
                              "is_story_live": false,
                              "pronouns": []
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/nasa/",
                          "username": "nasa"
                        },
                        "top_post_id": "DfIY71Lku89",
                        "unknown_fields": [],
                        "url": "https://www.instagram.com/nasa/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1899,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "528817151",
                          "url": "https://www.instagram.com/nasa/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramEngagementResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Engagement rate over an account's latest posts",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.engagement",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "engagement",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/hashtag": {
      "get": {
        "description": "Returns an Instagram hashtag's exact post count, or that Instagram restricts it, from its name or link. You also get its name, page link and Instagram's numeric tag ID.\n\nReturns `{data, meta}`: `data` is a `Hashtag` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/hashtag/ (Markdown: https://socialtap.dev/docs/reference/instagram/hashtag/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/hashtag/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/hashtag/"
        },
        "operationId": "instagram.hashtag.get",
        "parameters": [
          {
            "description": "An Instagram hashtag page link (instagram.com/explore/tags/cooking/), the page such a link opens logged out (instagram.com/popular/cooking/), or the hashtag itself with or without the # (cooking, #cooking). Hashtags are case-insensitive and may be in any script or be emoji (#料理, #❤️).",
            "example": "https://www.instagram.com/explore/tags/cooking/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "An Instagram hashtag page link (instagram.com/explore/tags/cooking/), the page such a link opens logged out (instagram.com/popular/cooking/), or the hashtag itself with or without the # (cooking, #cooking). Hashtags are case-insensitive and may be in any script or be emoji (#料理, #❤️).",
              "examples": [
                "https://www.instagram.com/explore/tags/cooking/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "description": null,
                        "id": "cooking",
                        "metrics": {
                          "post_count": 74151425
                        },
                        "name": "cooking",
                        "platform": "instagram",
                        "platform_specific": {
                          "instagram": {
                            "is_restricted": null,
                            "is_trending": null,
                            "tag_id": "17843688610006755"
                          }
                        },
                        "thumbnail_url": null,
                        "unknown_fields": [],
                        "url": "https://www.instagram.com/explore/tags/cooking/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 393,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "hashtag",
                          "id": "cooking",
                          "url": "https://www.instagram.com/explore/tags/cooking/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramHashtagResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact post count, tag ID and restricted status",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.hashtag",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "hashtag",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/hashtag_posts": {
      "get": {
        "description": "Returns the top public Instagram reels that carry a hashtag, a page at a time in Instagram's ranking, from its name or link. Each has its caption, hashtags, mentions, publish time, author, play, like and comment counts, length, cover and video file. Every reel returned has the hashtag in its caption.\n\nReturns `{data, page, meta}`: `data` holds up to 24 `Post` items (the shared schema, the same on every platform), Instagram's ranking of the hashtag's reels (its public results page's order). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/hashtag_posts/ (Markdown: https://socialtap.dev/docs/reference/instagram/hashtag_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/hashtag_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/hashtag_posts/"
        },
        "operationId": "instagram.hashtag_posts.list",
        "parameters": [
          {
            "description": "An Instagram hashtag page link (instagram.com/explore/tags/cooking/), the page such a link opens logged out (instagram.com/popular/cooking/), or the hashtag itself with or without the # (cooking, #cooking). Hashtags are case-insensitive and may be in any script or be emoji (#料理).",
            "example": "https://www.instagram.com/explore/tags/cooking/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "An Instagram hashtag page link (instagram.com/explore/tags/cooking/), the page such a link opens logged out (instagram.com/popular/cooking/), or the hashtag itself with or without the # (cooking, #cooking). Hashtags are case-insensitive and may be in any script or be emoji (#料理).",
              "examples": [
                "https://www.instagram.com/explore/tags/cooking/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Filters each page by published_at; the posts are in Instagram's order, not by time, so every page is still fetched.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Filters each page by published_at; the posts are in Instagram's order, not by time, so every page is still fetched.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 24,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 24,
              "maximum": 24,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/639810187_17875746018520843_3506369231816049829_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ig_cache_key=GIu6IiYLb4dz5YE-AKVEwSE9IKkwbmNDAQAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCR…",
                            "display_name": null,
                            "id": "75685712842",
                            "is_verified": false,
                            "url": "https://www.instagram.com/cookwithprincia/",
                            "username": "cookwithprincia"
                          },
                          "coauthors": [],
                          "duration_ms": 13700,
                          "hashtags": [
                            "explorepage",
                            "foryou",
                            "cooking"
                          ],
                          "id": "DVgF8OrE3WU",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 13700,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/643549505_17877652491520843_8763801214579496540_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=101&ig_cache_key=Mzg0NjEwMDIxMDkzMDY0NDM3MjE3ODc3NjUyNDg1NTIwODQz.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                              "type": "video",
                              "url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t16/f2/m69/AQP9FeQQXH0XeFbyMARMqfdHt4IXwzosGm3SEsStYQL8Do4oXsBNXNg0z8FjdbsI1uo8VCiA1WF6mgHl_N4ylv7Y.mp4?strext=1&_nc_cat=101&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=SCRUBB…",
                              "width": 1080
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 1838,
                            "like_count": 710870,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 30437214
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": null,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-03-05T11:42:17Z",
                          "text": "2 Minute Dahi Curry 🍛 \n\n#explorepage #foryou #cooking #recipes #dahicurry",
                          "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/643549505_17877652491520843_8763801214579496540_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=101&ig_cache_key=Mzg0NjEwMDIxMDkzMDY0NDM3MjE3ODc3NjUyNDg1NTIwODQz.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "coauthors",
                            "mentions"
                          ],
                          "url": "https://www.instagram.com/reel/DVgF8OrE3WU/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/561513192_17846006430582803_1220184481381762053_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=102&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid…",
                            "display_name": null,
                            "id": "77419174802",
                            "is_verified": false,
                            "url": "https://www.instagram.com/hkncook/",
                            "username": "hkncook"
                          },
                          "coauthors": [],
                          "duration_ms": 22407,
                          "hashtags": [
                            "cooking",
                            "toast",
                            "sandwich"
                          ],
                          "id": "DWwM5NYDDCk",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 22407,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/660549062_17872517145582803_5507446796631525086_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=102&ig_cache_key=Mzg2ODY0ODc4Nzg0MTY1OTA0NDE3ODcyNTE3MTM5NTgyODAz.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                              "type": "video",
                              "url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t2/f2/m86/AQPrp1tD-yFT4g2prsYZMfvywpBuSrw9lGLdG5Iu2YQAknFiKdLsx-w80nzUP2FIUzE-joHwIBVcdUyh_5a7-kJkozpGLTU9yjPwMBw.mp4?_nc_cat=102&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 1080
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 1533,
                            "like_count": 1297859,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 50892801
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": null,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-04-05T14:23:55Z",
                          "text": "PERFECT and FAST Sausage Eggs Toast 🥪\n\n#cooking #toast #sandwich #tost #kahvaltı",
                          "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/660549062_17872517145582803_5507446796631525086_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=102&ig_cache_key=Mzg2ODY0ODc4Nzg0MTY1OTA0NDE3ODcyNTE3MTM5NTgyODAz.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "coauthors",
                            "mentions"
                          ],
                          "url": "https://www.instagram.com/reel/DWwM5NYDDCk/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/464293922_917287770343534_6698961813091292531_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=105&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ss=7b6…",
                            "display_name": null,
                            "id": "70815842896",
                            "is_verified": false,
                            "url": "https://www.instagram.com/zap_eat/",
                            "username": "zap_eat"
                          },
                          "coauthors": [],
                          "duration_ms": 29013,
                          "hashtags": [
                            "asmr",
                            "cooking"
                          ],
                          "id": "DRFN52TiK3L",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 29013,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/581367857_17892410007362897_8997567808460424662_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=100&ig_cache_key=Mzc2NjQ3NzgxMzI4OTg4OTIyNzE3ODkyNDEwMDAxMzYyODk3.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                              "type": "video",
                              "url": "https://scontent-atl3-1.cdninstagram.com/o1/v/t2/f2/m86/AQOeQ4hNytwoNyDEQd1Y8SMkl3wB8lcv_438jhDRo3sw90Ectp7awXl4zEgDzdiPw4b0ASkkWoLpjiuqJuYFk9vTGgtddYuhaVdG5aA.mp4?_nc_cat=107&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 1080
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 737,
                            "like_count": 1959973,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 68996588
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": null,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2025-11-15T15:06:37Z",
                          "text": "Would you eat this?\n\nIngredients\nchicken breast: 1 pc\nolive oil: 100 ml (3.4 fl oz)\nsalt: 2 g (0.1 oz)\nflour: 150 g (5.3 oz)\neggs: 4 pc\nchips: 150 g (5.3 oz)\nparmesan: 50 g (1.8 oz)\nbutter: 70 g (2.5 oz)\nflour: 20 g (0.7 oz)\ncooking cream: 200 g (7.1 oz)\nsalt: 2 g (0.1 oz)\nmozzar…",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/581367857_17892410007362897_8997567808460424662_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=100&ig_cache_key=Mzc2NjQ3NzgxMzI4OTg4OTIyNzE3ODkyNDEwMDAxMzYyODk3.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "coauthors",
                            "mentions"
                          ],
                          "url": "https://www.instagram.com/reel/DRFN52TiK3L/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1215,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "hashtag",
                          "id": null,
                          "url": "https://www.instagram.com/explore/tags/cooking/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramHashtag_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Top reels that carry a hashtag",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.hashtag_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Instagram's ranking of the hashtag's reels (its public results page's order)",
          "page_max": 24,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/highlights": {
      "get": {
        "description": "Returns the story highlights on a public Instagram profile, in the order the profile shows them, from a username, profile link or user ID. Each has its ID, title, link, cover image and owner.\n\nReturns `{data, page, meta}`: `data` holds up to 10 `Playlist` items (the shared schema, the same on every platform), the order of the account's highlights tray on its profile. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/highlights/ (Markdown: https://socialtap.dev/docs/reference/instagram/highlights/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/highlights/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/highlights/"
        },
        "operationId": "instagram.highlights.list",
        "parameters": [
          {
            "description": "Instagram username with or without the @, a numeric user ID (528817151), or a profile URL (instagram.com/nasa, m.instagram.com, instagr.am, a /reels/ or /tagged/ tab, an instagram.com/_u/ app link, an instagram.com/stories/<username>/ link). A bare number is a user ID; a number no account has as its ID is looked up as a username, and @ before digits (@2020) always means the username.",
            "example": "nasa",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Instagram username with or without the @, a numeric user ID (528817151), or a profile URL (instagram.com/nasa, m.instagram.com, instagr.am, a /reels/ or /tagged/ tab, an instagram.com/_u/ app link, an instagram.com/stories/<username>/ link). A bare number is a user ID; a number no account has as its ID is looked up as a username, and @ before digits (@2020) always means the username.",
              "examples": [
                "nasa"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 10,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 10,
              "maximum": 10,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "description": null,
                          "id": "18195781759377100",
                          "is_collaborative": null,
                          "metrics": {
                            "post_count": null
                          },
                          "owner": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/29090066_159271188110124_1152068159029641216_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ig_cache_key=GBLhuwEsG5c225AAAAAAAADj9-wPbkULAAAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBE…",
                            "display_name": "NASA",
                            "id": "528817151",
                            "is_verified": true,
                            "url": "https://www.instagram.com/nasa/",
                            "username": "nasa"
                          },
                          "platform": "instagram",
                          "platform_specific": {},
                          "platform_type": "highlight",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/785745361_1537318174532484_931463605431094788_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_gid=SCRUBBED&_nc_s…",
                          "title": "Roman",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/stories/highlights/18195781759377100/"
                        },
                        {
                          "approximate_fields": [],
                          "description": null,
                          "id": "18123023338592759",
                          "is_collaborative": null,
                          "metrics": {
                            "post_count": null
                          },
                          "owner": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/29090066_159271188110124_1152068159029641216_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ig_cache_key=GBLhuwEsG5c225AAAAAAAADj9-wPbkULAAAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBE…",
                            "display_name": "NASA",
                            "id": "528817151",
                            "is_verified": true,
                            "url": "https://www.instagram.com/nasa/",
                            "username": "nasa"
                          },
                          "platform": "instagram",
                          "platform_specific": {},
                          "platform_type": "highlight",
                          "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.71878-15/658392542_1443405937523344_3996096698761393443_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=102&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=SCRUBBED&_nc_…",
                          "title": "Wallpapers",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/stories/highlights/18123023338592759/"
                        },
                        {
                          "approximate_fields": [],
                          "description": null,
                          "id": "18201653992314974",
                          "is_collaborative": null,
                          "metrics": {
                            "post_count": null
                          },
                          "owner": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/29090066_159271188110124_1152068159029641216_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ig_cache_key=GBLhuwEsG5c225AAAAAAAADj9-wPbkULAAAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBE…",
                            "display_name": "NASA",
                            "id": "528817151",
                            "is_verified": true,
                            "url": "https://www.instagram.com/nasa/",
                            "username": "nasa"
                          },
                          "platform": "instagram",
                          "platform_specific": {},
                          "platform_type": "highlight",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/718648521_1211952567628335_6800572588539032748_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=108&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_gid=SCRUBBED&_nc_…",
                          "title": "Artemis III",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/stories/highlights/18201653992314974/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 335,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "528817151",
                          "url": "https://www.instagram.com/nasa/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "end"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramHighlightsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Story highlights on a profile, with covers",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.highlights",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the order of the account's highlights tray on its profile",
          "page_max": 10,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "playlist",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/place": {
      "get": {
        "description": "Returns an Instagram location (a venue, landmark, neighborhood or city) with its address, coordinates and exact post count, from its link or ID. You also get its name, category, phone, price range, the business account linked to it, and the pictures of its top posts.\n\nReturns `{data, meta}`: `data` is a `Place` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/place/ (Markdown: https://socialtap.dev/docs/reference/instagram/place/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/place/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/place/"
        },
        "operationId": "instagram.place.get",
        "parameters": [
          {
            "description": "An Instagram location link (instagram.com/explore/locations/212988663/new-york-new-york/, as a post's location tag opens it; any name or tab after the ID) or the location's numeric ID (the number in that link).",
            "example": "https://www.instagram.com/explore/locations/767/the-standard-high-line/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "An Instagram location link (instagram.com/explore/locations/212988663/new-york-new-york/, as a post's location tag opens it; any name or tab after the ID) or the location's numeric ID (the number in that link).",
              "examples": [
                "https://www.instagram.com/explore/locations/767/the-standard-high-line/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "account": {
                          "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.2885-19/417936216_918658966510990_5379268959704848506_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=106&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ss=7b6…",
                          "display_name": null,
                          "id": "47087041514",
                          "is_verified": null,
                          "url": "https://www.instagram.com/thestandardhighline/",
                          "username": "thestandardhighline"
                        },
                        "address": "848 Washington St",
                        "approximate_fields": [],
                        "category": "Hotel",
                        "city": null,
                        "country_code": null,
                        "description": null,
                        "id": "767",
                        "images": [
                          {
                            "alt_text": null,
                            "duration_ms": null,
                            "expires_at": "2026-10-25T18:00:00Z",
                            "height": 1316,
                            "thumbnail_url": null,
                            "type": "image",
                            "url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/626497919_18559351216038401_9086769333717288659_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=104&ig_cache_key=MzgyNDQ5MDk0NTA5MzU3MTQwMw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                            "width": 1054
                          },
                          {
                            "alt_text": null,
                            "duration_ms": null,
                            "expires_at": "2026-10-25T18:00:00Z",
                            "height": 1857,
                            "thumbnail_url": null,
                            "type": "image",
                            "url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/642488693_18567012523003117_6640451626097873011_n.heic?stp=dst-jpg_e35_tt6&_nc_cat=100&ig_cache_key=Mzg0MjYzMTIxMDMyMTkxNzY5Mg%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt…",
                            "width": 1440
                          },
                          {
                            "alt_text": null,
                            "duration_ms": null,
                            "expires_at": "2026-10-25T18:00:00Z",
                            "height": 1920,
                            "thumbnail_url": null,
                            "type": "image",
                            "url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/670885119_18577030669049130_8283354781476415204_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=102&ig_cache_key=Mzg4MDMzMDQyNTkyNzg0NTc0Nw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                            "width": 1440
                          }
                        ],
                        "latitude": 40.74061,
                        "longitude": -74.00791,
                        "metrics": {
                          "image_count": null,
                          "post_count": 195474,
                          "review_count": null
                        },
                        "name": "The Standard, High Line",
                        "phone": null,
                        "platform": "instagram",
                        "platform_specific": {
                          "instagram": {
                            "facebook_place_id": null
                          }
                        },
                        "postal_code": "10014",
                        "price_range": 3,
                        "type": "venue",
                        "unknown_fields": [],
                        "url": "https://www.instagram.com/explore/locations/767/the-standard-high-line/",
                        "website_url": null
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 953,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "place",
                          "id": "767",
                          "url": "https://www.instagram.com/explore/locations/767/the-standard-high-line/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramPlaceResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Address, coordinates and exact post count",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.place",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "place",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/place_posts": {
      "get": {
        "description": "Returns the recent or top public Instagram posts tagged at a location, from its link or ID. Each has its caption, hashtags, mentions, publish time, photos or videos, author, the place it's tagged at with its coordinates, and like and comment counts.\n\nReturns `{data, page, meta}`: `data` holds up to 18 `Post` items (the shared schema, the same on every platform), newest first with sort=newest (the default), Instagram's Top posts for the location (its ranking) with sort=popular. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/place_posts/ (Markdown: https://socialtap.dev/docs/reference/instagram/place_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/place_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/place_posts/"
        },
        "operationId": "instagram.place_posts.list",
        "parameters": [
          {
            "description": "An Instagram location link (instagram.com/explore/locations/212988663/new-york-new-york/, as a post's location tag opens it; any name or tab after the ID) or the location's numeric ID (the number in that link).",
            "example": "https://www.instagram.com/explore/locations/212988663/new-york-new-york/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "An Instagram location link (instagram.com/explore/locations/212988663/new-york-new-york/, as a post's location tag opens it; any name or tab after the ID) or the location's numeric ID (the number in that link).",
              "examples": [
                "https://www.instagram.com/explore/locations/212988663/new-york-new-york/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. newest (default): the location's Recent tab, newest first. popular: its Top tab, Instagram's ranking of the posts there and, for a city or an area, at places inside it.",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "newest",
              "description": "Order of the results. newest (default): the location's Recent tab, newest first. popular: its Top tab, Instagram's ranking of the posts there and, for a city or an area, at places inside it.",
              "enum": [
                "newest",
                "popular"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 18,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 18,
              "maximum": 18,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/670615930_18077945933214471_2345937301934877217_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=102&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid…",
                            "display_name": null,
                            "id": "36427582470",
                            "is_verified": false,
                            "url": "https://www.instagram.com/fillysto/",
                            "username": "fillysto"
                          },
                          "coauthors": [],
                          "duration_ms": 7986,
                          "hashtags": [
                            "feet",
                            "viral"
                          ],
                          "id": "DfPS-ByN6tu",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 7986,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 2560,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t15.5256-10/825321038_4587988858127297_3075286220731044235_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=105&ig_cache_key=NDAyMTUxNjQxOTYyNjE1MDc2Ng%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23…",
                              "type": "video",
                              "url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t16/f2/m84/AQOv7yoNMI4v8okLQJoZ8jAFSp0iwJaRGT2wxLwLbfNNd5pCUSBXNkJMplQrFHSEt_1jB-tYKIydqZcd58pJveU5akKoxvHPaFHsxso.mp4?_nc_cat=105&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=…",
                              "width": 1440
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 0,
                            "like_count": 0,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": false,
                              "link": null,
                              "location": {
                                "id": "108424279189115",
                                "latitude": 40.7142,
                                "longitude": -74.0064,
                                "name": "New York, New York",
                                "url": "https://www.instagram.com/explore/locations/108424279189115/"
                              }
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-11-02T12:22:37Z",
                          "text": "Here, I think this belongs with you 🌸🤍 #feet #viral",
                          "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t15.5256-10/825321038_4587988858127297_3075286220731044235_n.jpg?stp=c0.248.640.640a_dst-jpg_e15_tt6&_nc_cat=105&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.cdninstagram.co…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/reel/DfPS-ByN6tu/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/831049335_18495629779097128_2536839403660674104_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=104&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid…",
                            "display_name": "Menzi Palabrica",
                            "id": "3064185127",
                            "is_verified": false,
                            "url": "https://www.instagram.com/menzip2/",
                            "username": "menzip2"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "DfPS91OowzA",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 2250,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/881396693_18502576525097128_3767119897427082798_n.jpg?stp=c0.225.1800.1800a_dst-jpg_e35_s1080x1080_sh2.08_tt6&_nc_cat=106&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-…",
                              "type": "image",
                              "url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/881396693_18502576525097128_3767119897427082798_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=106&ig_cache_key=NDAyMTUxNjQwNjE0NDMwNjM2OA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                              "width": 1800
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 0,
                            "like_count": 0,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": false,
                              "link": null,
                              "location": {
                                "id": "108424279189115",
                                "latitude": 40.7142,
                                "longitude": -74.0064,
                                "name": "New York, New York",
                                "url": "https://www.instagram.com/explore/locations/108424279189115/"
                              }
                            }
                          },
                          "platform_type": "post",
                          "published_at": "2026-11-02T12:22:20Z",
                          "text": null,
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/881396693_18502576525097128_3767119897427082798_n.jpg?stp=c0.225.1800.1800a_dst-jpg_e35_s1080x1080_sh2.08_tt6&_nc_cat=106&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/p/DfPS91OowzA/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.75761-19/503021357_17842805697506767_3789080071039190930_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=105&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid…",
                            "display_name": "Crafted by soul",
                            "id": "75164714766",
                            "is_verified": false,
                            "url": "https://www.instagram.com/craftedbysoul1/",
                            "username": "craftedbysoul1"
                          },
                          "coauthors": [],
                          "duration_ms": 64180,
                          "hashtags": [
                            "LandscapeArt",
                            "ForestPainting",
                            "ContemporaryArt"
                          ],
                          "id": "DfPSd32NYBy",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 64180,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1280,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/886235102_1787688402535983_6238101915428221736_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=110&ig_cache_key=NDAyMTUxNDIwOTkzMjQ0Mzc2MjE4NzgzNTE5NjY2MjYzNjk%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc…",
                              "type": "video",
                              "url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t2/f2/m86/AQO2UtArmmTTXAoGU-k2d313na9iIqF9zDiCSgK-vjEWL7dnmqXZ3PUKUnh-5bfAD8v41YVPKM2LPB5W6rF-02C1W8JUft0IIHBDZG0.mp4?_nc_cat=111&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 720
                            }
                          ],
                          "mentions": [
                            "a.zabrodzka"
                          ],
                          "metrics": {
                            "comment_count": 0,
                            "like_count": 0,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": false,
                              "link": null,
                              "location": {
                                "id": "108424279189115",
                                "latitude": 40.7142,
                                "longitude": -74.0064,
                                "name": "New York, New York",
                                "url": "https://www.instagram.com/explore/locations/108424279189115/"
                              }
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-11-02T12:22:19Z",
                          "text": "Agnieszka Zabrodzka is a Polish contemporary painter based in Warsaw, known for atmospheric forest landscapes, mirrored water reflections, and dreamlike scenes featuring white deer and cranes. Her acrylic paintings blend traditional landscape influences with Japanese-inspired gra…",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/886235102_1787688402535983_6238101915428221736_n.jpg?stp=c0.248.640.640a_dst-jpg_e15_tt6&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.cdninstagram.c…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/reel/DfPSd32NYBy/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 971,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "place",
                          "id": "212988663",
                          "url": "https://www.instagram.com/explore/locations/212988663/new-york-new-york/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramPlace_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Recent or top posts tagged at a location",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.place_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "orders": {
            "newest": "newest first",
            "popular": "Instagram's Top posts for the location (its ranking)"
          },
          "page_max": 18,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/playlist_stories": {
      "get": {
        "description": "Returns the stories saved to a public Instagram highlight, oldest first, from its link, share link or ID. Each has its image or video link at the best quality Instagram serves, cover, size, length, publish time, hashtag and link stickers, paid-partnership and AI labels, and the account that posted it.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Post` items (the shared schema, the same on every platform), oldest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/playlist_stories/ (Markdown: https://socialtap.dev/docs/reference/instagram/playlist_stories/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/playlist_stories/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/playlist_stories/"
        },
        "operationId": "instagram.playlist_stories.list",
        "parameters": [
          {
            "description": "An Instagram highlight: its link (instagram.com/stories/highlights/18195781759377100/), its share link (instagram.com/s/aGlnaGxpZ2h0OjE4MTk1NzgxNzU5Mzc3MTAw), or its numeric ID with or without the highlight: prefix (the number in that link). m.instagram.com links and tracking params are accepted.",
            "example": "https://www.instagram.com/stories/highlights/18142220566530226/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "An Instagram highlight: its link (instagram.com/stories/highlights/18195781759377100/), its share link (instagram.com/s/aGlnaGxpZ2h0OjE4MTk1NzgxNzU5Mzc3MTAw), or its numeric ID with or without the highlight: prefix (the number in that link). m.instagram.com links and tracking params are accepted.",
              "examples": [
                "https://www.instagram.com/stories/highlights/18195781759377100/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/869722290_18678730255039232_6152089836157107925_n.jpg?stp=dst-jpg_s150x150_tt6&efg=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_cat=1&_nc_oc=SCRUBBED&_nc_ohc=SCRUBBED&_nc_gid=SCRUBBED&edm=SCRUBBED&ccb=SCRUBBED&oh=SCR…",
                            "display_name": null,
                            "id": "290023231",
                            "is_verified": true,
                            "url": "https://www.instagram.com/realmadrid/",
                            "username": "realmadrid"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [
                            "realmadrid",
                            "welcomemourinho"
                          ],
                          "id": "3917364035672260085",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 2080,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/720486696_18631855093039232_5069687619599217584_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=110&ig_cache_key=MzkxNzM2NDAzNTY3MjI2MDA4NQ%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                              "width": 1170
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": false,
                              "link": {
                                "url": "https://www.realmadrid.com/es-ES/noticias/club/actualidad/comunicado-oficial-mourinho-11-06-2026"
                              },
                              "location": null
                            }
                          },
                          "platform_type": "story",
                          "published_at": "2026-06-11T19:30:04Z",
                          "text": null,
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/720486696_18631855093039232_5069687619599217584_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=110&ig_cache_key=MzkxNzM2NDAzNTY3MjI2MDA4NQ%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [
                            "mentions"
                          ],
                          "url": "https://www.instagram.com/stories/highlights/18142220566530226/?story_media_id=3917364035672260085_290023231"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/869722290_18678730255039232_6152089836157107925_n.jpg?stp=dst-jpg_s150x150_tt6&efg=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_cat=1&_nc_oc=SCRUBBED&_nc_ohc=SCRUBBED&_nc_gid=SCRUBBED&edm=SCRUBBED&ccb=SCRUBBED&oh=SCR…",
                            "display_name": null,
                            "id": "290023231",
                            "is_verified": true,
                            "url": "https://www.instagram.com/realmadrid/",
                            "username": "realmadrid"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "3917365496279774237",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 2080,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/721051652_18631856191039232_4694862753255422851_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=104&ig_cache_key=MzkxNzM2NTQ5NjI3OTc3NDIzNw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                              "width": 1170
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": false,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "story",
                          "published_at": "2026-06-11T19:32:58Z",
                          "text": null,
                          "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/721051652_18631856191039232_4694862753255422851_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=104&ig_cache_key=MzkxNzM2NTQ5NjI3OTc3NDIzNw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [
                            "mentions"
                          ],
                          "url": "https://www.instagram.com/stories/highlights/18142220566530226/?story_media_id=3917365496279774237_290023231"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/869722290_18678730255039232_6152089836157107925_n.jpg?stp=dst-jpg_s150x150_tt6&efg=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_cat=1&_nc_oc=SCRUBBED&_nc_ohc=SCRUBBED&_nc_gid=SCRUBBED&edm=SCRUBBED&ccb=SCRUBBED&oh=SCR…",
                            "display_name": null,
                            "id": "290023231",
                            "is_verified": true,
                            "url": "https://www.instagram.com/realmadrid/",
                            "username": "realmadrid"
                          },
                          "coauthors": [],
                          "duration_ms": 26267,
                          "hashtags": [],
                          "id": "3917374414358913962",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 26267,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/722637717_1888422201829905_6343097297541700097_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=106&ig_cache_key=MzkxNzM3NDQxNDM1ODkxMzk2Mg%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=2…",
                              "type": "video",
                              "url": "https://scontent-atl3-1.cdninstagram.com/o1/v/t2/f2/m78/AQPe8c_sX9oYvmyhUtolHBGD_Zo85so1NjIJZFS0Pf4bDyammWgYguAtgtRra5B5miE1IXI3ugBVUZHkOV30Xwit5iA7FKsqnLwNAac.mp4?_nc_cat=108&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 1080
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": true,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "story",
                          "published_at": "2026-06-11T19:50:41Z",
                          "text": null,
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/722637717_1888422201829905_6343097297541700097_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=106&ig_cache_key=MzkxNzM3NDQxNDM1ODkxMzk2Mg%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=2…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "mentions"
                          ],
                          "url": "https://www.instagram.com/stories/highlights/18142220566530226/?story_media_id=3917374414358913962_290023231"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1038,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "playlist",
                          "id": "18142220566530226",
                          "url": "https://www.instagram.com/stories/highlights/18142220566530226/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "end"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramPlaylist_storiesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Stories saved to a highlight, with media links",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.playlist_stories",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "oldest first",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/post": {
      "get": {
        "description": "Returns a public Instagram post, reel or carousel with its caption, author, media, and like, comment and view counts, from its link or shortcode. You also get hashtags, mentions, collaborators, the publish time, and every carousel item's image or video with its size, length and alt text.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/post/ (Markdown: https://socialtap.dev/docs/reference/instagram/post/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/post/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/post/"
        },
        "operationId": "instagram.post.get",
        "parameters": [
          {
            "description": "Instagram post, reel or carousel URL (instagram.com/p/…, /reel/…, /reels/…, /tv/…, /<username>/p/…, m.instagram.com, instagr.am, instagram.com/share/… links) or a raw shortcode. Tracking params and img_index are ignored: the whole post is returned.",
            "example": "https://www.instagram.com/reel/De1S3KpCXf0/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Instagram post, reel or carousel URL (instagram.com/p/…, /reel/…, /reels/…, /tv/…, /<username>/p/…, m.instagram.com, instagr.am, instagram.com/share/… links) or a raw shortcode. Tracking params and img_index are ignored: the whole post is returned.",
              "examples": [
                "https://www.instagram.com/reel/De1S3KpCXf0/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/683576066_18653628823019133_9051036240972105113_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=S…",
                          "display_name": "National Geographic",
                          "id": "787132",
                          "is_verified": true,
                          "url": "https://www.instagram.com/natgeo/",
                          "username": "natgeo"
                        },
                        "coauthors": [
                          {
                            "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.2885-19/293493364_162817252949028_8275460966213229030_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=108&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ss=7b6…",
                            "display_name": "National Geographic Society",
                            "id": "4757225830",
                            "is_verified": true,
                            "url": "https://www.instagram.com/natgeosociety/",
                            "username": "natgeosociety"
                          },
                          {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/11419091_505296402966021_797003013_a.jpg?_nc_cat=101&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ss=7b689&oh=SCRUBBED&oe=F2A52380",
                            "display_name": "Joel Sartore- Photo Ark",
                            "id": "225429667",
                            "is_verified": true,
                            "url": "https://www.instagram.com/joelsartore/",
                            "username": "joelsartore"
                          },
                          {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/681945023_18592998970017301_7811445524976503069_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=S…",
                            "display_name": "National Geographic Animals",
                            "id": "1029649300",
                            "is_verified": true,
                            "url": "https://www.instagram.com/natgeoanimals/",
                            "username": "natgeoanimals"
                          }
                        ],
                        "duration_ms": 23744,
                        "hashtags": [
                          "PhotoArk"
                        ],
                        "id": "De1S3KpCXf0",
                        "is_nsfw": null,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": null,
                        "media": [
                          {
                            "alt_text": "Video by National Geographic on October 23, 2026. May be an image of snail and text.",
                            "duration_ms": 23744,
                            "expires_at": "2026-10-25T18:00:00Z",
                            "height": 1920,
                            "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/862543567_18711062458019133_8845814561108513720_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=105&ig_cache_key=NDAxNDE5NzU5ODcwNDk5MDE5NjE4NzExMDYyNDUyMDE5MTMz.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                            "type": "video",
                            "url": "https://scontent-atl3-1.cdninstagram.com/o1/v/t2/f2/m86/AQO0Zc3E_eoYHXxPOVvPDNzjiHnCGoREl8vxeookIy4831a0VLAN6T9CITX0dyH2cQS6Dy0fs5SGxYC42fWpG2JeAvlnP9yrsgmHUk8.mp4?_nc_cat=106&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                            "width": 1080
                          }
                        ],
                        "mentions": [
                          "joelsartore",
                          "natgeoanimals",
                          "natgeosociety"
                        ],
                        "metrics": {
                          "comment_count": 238,
                          "like_count": 68253,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": null,
                          "share_count": null,
                          "view_count": 759188
                        },
                        "platform": "instagram",
                        "platform_specific": {
                          "instagram": {
                            "is_ai_generated": null,
                            "link": null,
                            "location": null
                          }
                        },
                        "platform_type": "reel",
                        "published_at": "2026-10-23T10:01:35Z",
                        "text": "Warning—looking at nudibranchs may cause excessive awe. @joelsartore loves these little creatures, and so do we. 💛🧡🩷\n\nWe’re celebrating 20 years of the National Geographic #PhotoArk, an audacious project documenting the world's incredible biodiversity and highlighting the importa…",
                        "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/862543567_18711062458019133_8845814561108513720_n.jpg?stp=dst-jpg_e35_s640x640_tt6&_nc_cat=105&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc…",
                        "title": null,
                        "type": "video",
                        "unknown_fields": [],
                        "url": "https://www.instagram.com/reel/De1S3KpCXf0/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 986,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "De1S3KpCXf0",
                          "url": "https://www.instagram.com/reel/De1S3KpCXf0/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramPostResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Post, reel or carousel with media, likes and views",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.post",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/posts": {
      "get": {
        "description": "Returns a public Instagram account's posts, reels and carousels, newest first, a page at a time, from a username, profile link or user ID. Each has its caption, hashtags, mentions, publish time, collaborators, tagged accounts, media, and like, comment and view counts, with pinned posts marked.\n\nReturns `{data, page, meta}`: `data` holds up to 12 `Post` items (the shared schema, the same on every platform), newest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/posts/ (Markdown: https://socialtap.dev/docs/reference/instagram/posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/posts/"
        },
        "operationId": "instagram.posts.list",
        "parameters": [
          {
            "description": "Instagram username with or without the @, a numeric user ID (528817151), or a profile URL (instagram.com/nasa, m.instagram.com, instagr.am, a /reels/ or /tagged/ tab, an instagram.com/_u/ app link). A bare number is a user ID; a number no account has as its ID is looked up as a username, and @ before digits (@2020) always means the username.",
            "example": "nasa",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Instagram username with or without the @, a numeric user ID (528817151), or a profile URL (instagram.com/nasa, m.instagram.com, instagr.am, a /reels/ or /tagged/ tab, an instagram.com/_u/ app link). A bare number is a user ID; a number no account has as its ID is looked up as a username, and @ before digits (@2020) always means the username.",
              "examples": [
                "nasa"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 12,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 12,
              "maximum": 12,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/29090066_159271188110124_1152068159029641216_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ss=7b689&…",
                            "display_name": "NASA",
                            "id": "528817151",
                            "is_verified": true,
                            "url": "https://www.instagram.com/nasa/",
                            "username": "nasa"
                          },
                          "coauthors": [
                            {
                              "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/93880139_247576663101568_4560165171292536832_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ss=7b689&…",
                              "display_name": "NASA Solar System Exploration",
                              "id": "1611722079",
                              "is_verified": true,
                              "url": "https://www.instagram.com/nasasolarsystem/",
                              "username": "nasasolarsystem"
                            },
                            {
                              "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/670016304_18577283653042671_4689932669633757619_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=S…",
                              "display_name": "NASA Artemis",
                              "id": "1104426670",
                              "is_verified": true,
                              "url": "https://www.instagram.com/nasaartemis/",
                              "username": "nasaartemis"
                            }
                          ],
                          "duration_ms": 43767,
                          "hashtags": [
                            "NASA",
                            "ArtemisII",
                            "Artemis"
                          ],
                          "id": "DeTUk4sDSp-",
                          "is_nsfw": null,
                          "is_pinned": true,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 43767,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1908,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/842191580_18656578867049152_4200499629839780998_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=111&ig_cache_key=NDAwNDYzNDk4OTM2MjQ4OTk4MjE4NjU2NTc4ODYxMDQ5MTUy.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                              "type": "video",
                              "url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t2/f2/m86/AQNUvreb47JFAC3mKM7kF_weYHzhiVF-MfERm99CfyBTok0ezeRdbVW8cH5NXn4mxO8gVi6j1GQ2RU9i4ByvKCLVPHdDruUpsCKYDQI.mp4?_nc_cat=105&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 1074
                            }
                          ],
                          "mentions": [
                            "nasaartemis",
                            "nasasolarsystem"
                          ],
                          "metrics": {
                            "comment_count": 7628,
                            "like_count": 755597,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 11075076
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": false,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-10-10T15:15:02Z",
                          "text": "POV: you're watching the Earth set\n\nWe just released hundreds of new images and hours of new audio from our Artemis II mission around the Moon this spring. Check out our link in bio for the Artemis II Preliminary Lunar Science Report.\n\n#NASA #ArtemisII #Artemis",
                          "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/842191580_18656578867049152_4200499629839780998_n.jpg?stp=c0.417.1074.1074a_dst-jpg_e15_tt6&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.cdninstagra…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/reel/DeTUk4sDSp-/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/432029380_939863124412845_4074172309041694202_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ss=7b689…",
                            "display_name": "NASA Webb Telescope",
                            "id": "549313808",
                            "is_verified": true,
                            "url": "https://www.instagram.com/nasawebb/",
                            "username": "nasawebb"
                          },
                          "coauthors": [
                            {
                              "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/437785305_1498177207718392_5285428334541669140_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=105&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ss=7b…",
                              "display_name": "NASA Universe",
                              "id": "65495240044",
                              "is_verified": true,
                              "url": "https://www.instagram.com/nasauniverse/",
                              "username": "nasauniverse"
                            },
                            {
                              "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/29090066_159271188110124_1152068159029641216_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ss=7b689&…",
                              "display_name": "NASA",
                              "id": "528817151",
                              "is_verified": true,
                              "url": "https://www.instagram.com/nasa/",
                              "username": "nasa"
                            }
                          ],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "DeJ28eTxo4s",
                          "is_nsfw": null,
                          "is_pinned": true,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1872,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/838879752_18633093571001809_7013098794556155636_n.jpg?stp=c64.0.1872.1872a_dst-jpg_e35_s1080x1080_sh2.08_tt6&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-a…",
                              "type": "image",
                              "url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/838879752_18633093571001809_7013098794556155636_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=109&ig_cache_key=NDAwMTk3MTM5NDExOTYzNDQ3Ng%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                              "width": 2000
                            }
                          ],
                          "mentions": [
                            "NASAWebb",
                            "nasa",
                            "nasauniverse"
                          ],
                          "metrics": {
                            "comment_count": 1027,
                            "like_count": 290040,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": false,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "post",
                          "published_at": "2026-10-06T13:10:11Z",
                          "text": "Brewing up new stars 🪄\n \n@NASAWebb’s unique view of the stellar nursery known as NGC 7129 reveals numerous stars formerly hidden in this cosmic cauldron. \n \nStars begin their life in cold, dense regions of dust and gas, hiding from view of most telescopes. Webb’s high degree of i…",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/838879752_18633093571001809_7013098794556155636_n.jpg?stp=c64.0.1872.1872a_dst-jpg_e35_s1080x1080_sh2.08_tt6&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-a…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/p/DeJ28eTxo4s/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/29090066_159271188110124_1152068159029641216_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ss=7b689&…",
                            "display_name": "NASA",
                            "id": "528817151",
                            "is_verified": true,
                            "url": "https://www.instagram.com/nasa/",
                            "username": "nasa"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [
                            "NASA",
                            "Space",
                            "Stars"
                          ],
                          "id": "DeAYvsnn4la",
                          "is_nsfw": null,
                          "is_pinned": true,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1350,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/831222439_18653890615049152_5346150317938845760_n.jpg?stp=c0.135.1080.1080a_dst-jpg_e15_s1080x1080_tt6&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.…",
                              "type": "image",
                              "url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/831222439_18653890615049152_5346150317938845760_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=110&ig_cache_key=Mzk5OTMwNDc1ODAwMTk1MzE5OA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                              "width": 1080
                            },
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1350,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/830418338_18653890612049152_312587861543217627_n.jpg?stp=c0.135.1080.1080a_dst-jpg_e15_s1080x1080_tt6&_nc_cat=100&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.c…",
                              "type": "image",
                              "url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/830418338_18653890612049152_312587861543217627_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=100&ig_cache_key=Mzk5OTMwNDc1ODM0NjExNzEyOA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=2…",
                              "width": 1080
                            },
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1350,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/831354642_18653890627049152_4381034991606753149_n.jpg?stp=c0.135.1080.1080a_dst-jpg_e15_s1080x1080_tt6&_nc_cat=104&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.…",
                              "type": "image",
                              "url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/831354642_18653890627049152_4381034991606753149_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=104&ig_cache_key=Mzk5OTMwNDc2MDcwMzExNzQxOA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                              "width": 1080
                            }
                          ],
                          "mentions": [
                            "NASAWebb"
                          ],
                          "metrics": {
                            "comment_count": 5550,
                            "like_count": 1353320,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": false,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "post",
                          "published_at": "2026-10-02T20:52:45Z",
                          "text": "Swipe for countless stars\n\nSagittarius B2 is the most massive and most active star-forming region in the Milky Way. It produces half of the stars in our home galaxy’s core.\n\nThis image of Sagittarius B2 was taken by our @NASAWebb telescope.\n\n#NASA #Space #Stars",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/831222439_18653890615049152_5346150317938845760_n.jpg?stp=c0.135.1080.1080a_dst-jpg_e15_s1080x1080_tt6&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.…",
                          "title": null,
                          "type": "carousel",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/p/DeAYvsnn4la/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1116,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "528817151",
                          "url": "https://www.instagram.com/nasa/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramPostsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Posts, reels and carousels from a profile",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "page_max": 12,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/profile": {
      "get": {
        "description": "Returns a public Instagram profile from a username, profile link or user ID, with its exact follower, following and post counts. It also has the bio, bio links, name, verified badge, full-size profile picture, whether the account is private, its category and account type, its Meta-wide ID, and whether it has a story up.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/profile/ (Markdown: https://socialtap.dev/docs/reference/instagram/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/profile/"
        },
        "operationId": "instagram.profile.get",
        "parameters": [
          {
            "description": "Instagram username with or without the @ (natgeo, @natgeo), a numeric user ID (787132), or a profile link (instagram.com/natgeo, with or without a tab such as /reels/ or /tagged/, m.instagram.com, instagr.am, instagram.com/_u/natgeo, instagram.com/stories/natgeo/, with any query such as ?igsh=…). Usernames are case-insensitive. A bare number is a user ID; a number no account has as its ID is looked up as a username, and @ before digits (@2020) always means the username.",
            "example": "https://www.instagram.com/natgeo/",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Instagram username with or without the @ (natgeo, @natgeo), a numeric user ID (787132), or a profile link (instagram.com/natgeo, with or without a tab such as /reels/ or /tagged/, m.instagram.com, instagr.am, instagram.com/_u/natgeo, instagram.com/stories/natgeo/, with any query such as ?igsh=…). Usernames are case-insensitive. A bare number is a user ID; a number no account has as its ID is looked up as a username, and @ before digits (@2020) always means the username.",
              "examples": [
                "natgeo"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/683576066_18653628823019133_9051036240972105113_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=S…",
                        "banner_url": null,
                        "bio": "Step into wonder and find your inner explorer with National Geographic 🌎",
                        "category": null,
                        "country_code": null,
                        "created_at": null,
                        "display_name": "National Geographic",
                        "external_links": [
                          {
                            "title": null,
                            "url": "http://visitstore.bio/natgeo"
                          },
                          {
                            "title": "Subscribe Here!",
                            "url": "https://ngmdomsubs.nationalgeographic.com/servlet/OrdersGateway?cds_mag_code=NGM&cds_page_id=283562&cds_response_key=I5FX10002"
                          }
                        ],
                        "id": "787132",
                        "is_private": false,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 268266804,
                          "following_count": 195,
                          "post_count": 32123,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "instagram",
                        "platform_specific": {
                          "instagram": {
                            "account_type": null,
                            "fbid": "17841400573960012",
                            "is_highlights_shown": true,
                            "is_memorialized": false,
                            "is_story_live": true,
                            "pronouns": []
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://www.instagram.com/natgeo/",
                        "username": "natgeo"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1516,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "787132",
                          "url": "https://www.instagram.com/natgeo/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact follower counts, bio and bio links",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/reels": {
      "get": {
        "description": "Returns the reels on a public Instagram account's reels tab, newest first after pinned ones, from a username, profile link or user ID. Each has its play, like and comment counts, caption, hashtags, mentions, publish time, collaborators, tagged accounts, paid-partnership label and video file with its size, length and cover. Collab reels another account published show too, with that account as author.\n\nReturns `{data, page, meta}`: `data` holds up to 12 `Post` items (the shared schema, the same on every platform), newest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/reels/ (Markdown: https://socialtap.dev/docs/reference/instagram/reels/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/reels/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/reels/"
        },
        "operationId": "instagram.reels.list",
        "parameters": [
          {
            "description": "Instagram username with or without the @, a numeric user ID (528817151), or a profile URL (instagram.com/nasa, its /reels/ tab, m.instagram.com, instagr.am, an instagram.com/_u/ app link). A bare number is a user ID; a number no account has as its ID is looked up as a username, and @ before digits (@2020) always means the username.",
            "example": "nasa",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Instagram username with or without the @, a numeric user ID (528817151), or a profile URL (instagram.com/nasa, its /reels/ tab, m.instagram.com, instagr.am, an instagram.com/_u/ app link). A bare number is a user ID; a number no account has as its ID is looked up as a username, and @ before digits (@2020) always means the username.",
              "examples": [
                "nasa"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 12,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 12,
              "maximum": 12,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.2885-19/11421977_902607023152688_677352411_a.jpg?_nc_cat=106&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ss=7b689&oh=SCRUBBED&oe=F2A52380",
                            "display_name": "NASA’s Johnson Space Center",
                            "id": "673882723",
                            "is_verified": true,
                            "url": "https://www.instagram.com/nasajohnson/",
                            "username": "nasajohnson"
                          },
                          "coauthors": [
                            {
                              "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/524387219_18515253022013390_8734863048221656878_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=S…",
                              "display_name": "International Space Station",
                              "id": "953293389",
                              "is_verified": true,
                              "url": "https://www.instagram.com/iss/",
                              "username": "iss"
                            },
                            {
                              "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/29090066_159271188110124_1152068159029641216_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ig_cache_key=GBLhuwEsG5c225AAAAAAAADj9-wPbkULAAAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBE…",
                              "display_name": "NASA",
                              "id": "528817151",
                              "is_verified": true,
                              "url": "https://www.instagram.com/nasa/",
                              "username": "nasa"
                            }
                          ],
                          "duration_ms": 41377,
                          "hashtags": [],
                          "id": "DfF3eqGSKKc",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 41377,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/865204930_18640535563026724_3353517023594775034_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=109&ig_cache_key=NDAxODg2MjI0MTg0MzAyODYzNjE4NjQwNTM1NTYwMDI2NzI0.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                              "type": "video",
                              "url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t2/f2/m86/AQMgO65IBSO4D1Fg1v8qWRLjCR7N-LaX4H_sPQeyoyjFQE149o094RWHdy1qn9GBy1VHAND2Io7UoTGpUBgIXE-YSbD4UnaCrO694xk.mp4?_nc_cat=102&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 1080
                            }
                          ],
                          "mentions": [
                            "nasa",
                            "iss",
                            "astro_anil"
                          ],
                          "metrics": {
                            "comment_count": 141,
                            "like_count": 13650,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 2400093
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": false,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-10-29T20:35:35Z",
                          "text": "More power loading. 🔋\n\nToday, NASA astronaut Anil Menon and CSA (Canadian Space Agency) astronaut Joshua Kutryk conducted a spacewalk to install the 7th of 8 new roll out solar arrays. The final new array is slated to be installed during the Nov. 5 spacewalk, increasing the stati…",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/865204930_18640535563026724_3353517023594775034_n.jpg?stp=c0.280.720.720a_dst-jpg_e15_tt6&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-1.cdninstagram.…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/reel/DfF3eqGSKKc/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/601447735_17843472855663003_3861542852440345349_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=S…",
                            "display_name": "NASA Administrator Jared Isaacman",
                            "id": "79712351002",
                            "is_verified": true,
                            "url": "https://www.instagram.com/nasaadmin/",
                            "username": "nasaadmin"
                          },
                          "coauthors": [
                            {
                              "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.2885-19/131437854_403510010866209_8747594753463415027_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ss=7b6…",
                              "display_name": "The University of Alabama",
                              "id": "1934718827",
                              "is_verified": true,
                              "url": "https://www.instagram.com/univofalabama/",
                              "username": "univofalabama"
                            },
                            {
                              "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/29090066_159271188110124_1152068159029641216_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ig_cache_key=GBLhuwEsG5c225AAAAAAAADj9-wPbkULAAAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBE…",
                              "display_name": "NASA",
                              "id": "528817151",
                              "is_verified": true,
                              "url": "https://www.instagram.com/nasa/",
                              "username": "nasa"
                            },
                            {
                              "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.2885-19/412351457_388761240176236_8075991643457937896_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=109&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ss=7b6…",
                              "display_name": "Alabama Football",
                              "id": "461078008",
                              "is_verified": true,
                              "url": "https://www.instagram.com/alabamafbl/",
                              "username": "alabamafbl"
                            }
                          ],
                          "duration_ms": 61508,
                          "hashtags": [],
                          "id": "De7XCa_TJ4h",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 61508,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1078,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/858088880_1909652077075572_3321833479248057878_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=101&ig_cache_key=NDAxNTkwNDgxNDIxODkxMTI2NTE5MDk2NTIwNzM3NDIyMzk%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc…",
                              "type": "video",
                              "url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t2/f2/m86/AQO_XE-Eozfv9EhJgpBw8CpgqEydxrCcLTTmdJ4OmJL4u8TmjEREW4NyjX7EoxhsUiVfVbZseRJAIb1F9nUfjAsGTOK4bYFiS-v5fw4.mp4?_nc_cat=105&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 1916
                            }
                          ],
                          "mentions": [
                            "nasa",
                            "ua_athletics",
                            "alabamafbl"
                          ],
                          "metrics": {
                            "comment_count": 243,
                            "like_count": 54940,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 4788817
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": false,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-10-25T18:35:11Z",
                          "text": "This is how @nasa does game day. Roll Tide! 🚀🏈",
                          "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/858088880_1909652077075572_3321833479248057878_n.jpg?stp=c0.472.1215.1215a_dst-jpg_e35_s1080x1080_sh2.08_tt6&_nc_cat=101&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-a…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/reel/De7XCa_TJ4h/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/29090066_159271188110124_1152068159029641216_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ig_cache_key=GBLhuwEsG5c225AAAAAAAADj9-wPbkULAAAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBE…",
                            "display_name": "NASA",
                            "id": "528817151",
                            "is_verified": true,
                            "url": "https://www.instagram.com/nasa/",
                            "username": "nasa"
                          },
                          "coauthors": [
                            {
                              "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/670016304_18577283653042671_4689932669633757619_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=S…",
                              "display_name": "NASA Artemis",
                              "id": "1104426670",
                              "is_verified": true,
                              "url": "https://www.instagram.com/nasaartemis/",
                              "username": "nasaartemis"
                            },
                            {
                              "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/601447735_17843472855663003_3861542852440345349_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=S…",
                              "display_name": "NASA Administrator Jared Isaacman",
                              "id": "79712351002",
                              "is_verified": true,
                              "url": "https://www.instagram.com/nasaadmin/",
                              "username": "nasaadmin"
                            }
                          ],
                          "duration_ms": 59883,
                          "hashtags": [
                            "Artemis"
                          ],
                          "id": "De2t82PPyx9",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 59883,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/859070372_18661402093049152_3071139610491516778_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=104&ig_cache_key=NDAxNDU5ODIxMTM0NjgzNjYwNTE4NjYxNDAyMDg3MDQ5MTUy.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                              "type": "video",
                              "url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t2/f2/m86/AQNTkECBw2suz97dudN4wjd5tp7fZgWYJZB6PwTVUGMQU9r4E08_w4KcBLpaInhz4kASzQbv8D4AqHGg8nn8IWBidZ5OR5QfmdqpvN0.mp4?_nc_cat=102&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 1080
                            }
                          ],
                          "mentions": [
                            "nasaartemis",
                            "nasaadmin"
                          ],
                          "metrics": {
                            "comment_count": 508,
                            "like_count": 64972,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 3173173
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": false,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-10-23T23:20:57Z",
                          "text": "We are not slowing down. 🚀\n\nOur #Artemis III mission will send four astronauts to low Earth orbit next year to test critical systems needed for future lunar landings and we’re accelerating efforts to ensure the success of Artemis IV, the first Artemis mission on the lunar surface…",
                          "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/859070372_18661402093049152_3071139610491516778_n.jpg?stp=c0.280.720.720a_dst-jpg_e15_tt6&_nc_cat=104&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.cdninstagram.…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/reel/De2t82PPyx9/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1199,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "528817151",
                          "url": "https://www.instagram.com/nasa/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramReelsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Pinned then newest, with play counts",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.reels",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "page_max": 12,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/search_hashtags": {
      "get": {
        "description": "Returns the Instagram hashtags that match a word or the start of a hashtag, with exact post counts, in Instagram's own ranking. Each has its name, page link and numeric tag ID. The cursor pages well past the first screen Instagram's search shows.\n\nReturns `{data, page, meta}`: `data` holds up to 55 `Hashtag` items (the shared schema, the same on every platform), Instagram's search ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/search_hashtags/ (Markdown: https://socialtap.dev/docs/reference/instagram/search_hashtags/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/search_hashtags/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/search_hashtags/"
        },
        "operationId": "instagram.search_hashtags.list",
        "parameters": [
          {
            "description": "What to search hashtags for: a word or the start of a hashtag, with or without the # (cooking, #sourdough, 料理, ❤). Instagram matches hashtags that start with it or resemble it, ignoring case and spaces.",
            "example": "cooking",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to search hashtags for: a word or the start of a hashtag, with or without the # (cooking, #sourdough, 料理, ❤). Instagram matches hashtags that start with it or resemble it, ignoring case and spaces.",
              "examples": [
                "cooking"
              ],
              "maxLength": 150,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 55,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 55,
              "maximum": 55,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "description": null,
                          "id": "cooking",
                          "metrics": {
                            "post_count": 74152476
                          },
                          "name": "cooking",
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_restricted": null,
                              "is_trending": null,
                              "tag_id": "17843688610006755"
                            }
                          },
                          "thumbnail_url": null,
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/explore/tags/cooking/"
                        },
                        {
                          "approximate_fields": [],
                          "description": null,
                          "id": "letsgetcooking",
                          "metrics": {
                            "post_count": 125675
                          },
                          "name": "letsgetcooking",
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_restricted": null,
                              "is_trending": null,
                              "tag_id": "17843752486003531"
                            }
                          },
                          "thumbnail_url": null,
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/explore/tags/letsgetcooking/"
                        },
                        {
                          "approximate_fields": [],
                          "description": null,
                          "id": "homecookingrocks",
                          "metrics": {
                            "post_count": 107599
                          },
                          "name": "homecookingrocks",
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_restricted": null,
                              "is_trending": null,
                              "tag_id": "17841545602105185"
                            }
                          },
                          "thumbnail_url": null,
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/explore/tags/homecookingrocks/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 366,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramSearch_hashtagsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Hashtags matching a word, with exact post counts",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.search_hashtags",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Instagram's search ranking (most relevant first)",
          "page_max": 55,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "hashtag",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/search_places": {
      "get": {
        "description": "Returns the Instagram locations a web search finds for your words, like a venue's name, a kind of place or a city, with their links. Each has its name, and its category and post count when the search index shows them. Add fill=true to get each location's current Instagram record (category, coordinates, address, exact post count) in the same response.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/search_places/ (Markdown: https://socialtap.dev/docs/reference/instagram/search_places/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/search_places/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/search_places/"
        },
        "operationId": "instagram.search_places.list",
        "parameters": [
          {
            "description": "Words to find Instagram locations by, as a web search reads them: a venue's name, a kind of place and a city, a neighborhood (blue bottle coffee, rooftop bar brooklyn, \"central park\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and intitle:, inurl: and intext: count as plain words.",
            "example": "rooftop bar brooklyn",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find Instagram locations by, as a web search reads them: a venue's name, a kind of place and a city, a neighborhood (blue bottle coffee, rooftop bar brooklyn, \"central park\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and intitle:, inurl: and intext: count as plain words.",
              "examples": [
                "rooftop bar brooklyn"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "place.metrics.post_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.instagram.com/explore/locations/303286820149120/hookah-bar-rooftop/",
                          "place": {
                            "address": null,
                            "category": null,
                            "city": null,
                            "country_code": null,
                            "id": null,
                            "latitude": null,
                            "longitude": null,
                            "metrics": {
                              "image_count": null,
                              "post_count": 618,
                              "review_count": null
                            },
                            "name": "Hookah Bar & Rooftop",
                            "url": "https://www.instagram.com/explore/locations/303286820149120/"
                          },
                          "platform": "instagram",
                          "platform_specific": {},
                          "position": 0,
                          "post": null,
                          "profile": null,
                          "snippet": "618 Posts - See Instagram photos and videos taken at ‘Hookah Bar & Rooftop’",
                          "sound": null,
                          "title": "Hookah Bar & Rooftop on Instagram • Photos and Videos",
                          "type": "place",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/explore/locations/303286820149120/"
                        },
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.instagram.com/explore/locations/1736401643338479/tipsy-stories-rooftop-bar/",
                          "place": {
                            "address": null,
                            "category": null,
                            "city": null,
                            "country_code": null,
                            "id": null,
                            "latitude": null,
                            "longitude": null,
                            "metrics": {
                              "image_count": null,
                              "post_count": null,
                              "review_count": null
                            },
                            "name": null,
                            "url": "https://www.instagram.com/explore/locations/1736401643338479/"
                          },
                          "platform": "instagram",
                          "platform_specific": {},
                          "position": 1,
                          "post": null,
                          "profile": null,
                          "snippet": "We cannot provide a description for this page right now",
                          "sound": null,
                          "title": "Instagram",
                          "type": "place",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/explore/locations/1736401643338479/"
                        },
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.instagram.com/explore/locations/1891704361093768/14-stories-rooftop-bar/",
                          "place": {
                            "address": null,
                            "category": null,
                            "city": null,
                            "country_code": null,
                            "id": null,
                            "latitude": null,
                            "longitude": null,
                            "metrics": {
                              "image_count": null,
                              "post_count": null,
                              "review_count": null
                            },
                            "name": "14 Stories Rooftop Bar",
                            "url": "https://www.instagram.com/explore/locations/1891704361093768/"
                          },
                          "platform": "instagram",
                          "platform_specific": {},
                          "position": 2,
                          "post": null,
                          "profile": null,
                          "snippet": "We cannot provide a description for this page right now",
                          "sound": null,
                          "title": "14 Stories Rooftop Bar",
                          "type": "place",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/explore/locations/1891704361093768/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1277,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramSearch_placesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Locations by name, kind of place or city",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.search_places",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/search_posts": {
      "get": {
        "description": "Returns the public Instagram reels for a keyword, as Instagram's logged-out search shows them, a page at a time in its own ranking. Each has its link, caption, hashtags, mentions, publish time, author with verified badge, play, like and comment counts, length, cover and video file.\n\nReturns `{data, page, meta}`: `data` holds up to 24 `Post` items (the shared schema, the same on every platform), Instagram's ranking for the keyword (its popular page's order). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/search_posts/ (Markdown: https://socialtap.dev/docs/reference/instagram/search_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/search_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/search_posts/"
        },
        "operationId": "instagram.search_posts.list",
        "parameters": [
          {
            "description": "Keywords, matched as Instagram's public results pages match them (instagram.com/popular/<keywords>/): case, a leading # or @ and hyphens are ignored.",
            "example": "vegan pasta recipe",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Keywords, matched as Instagram's public results pages match them (instagram.com/popular/<keywords>/): case, a leading # or @ and hyphens are ignored.",
              "examples": [
                "vegan pasta recipe"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Filters each page by published_at; the results are in Instagram's order, not by time, so every page is still fetched.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Filters each page by published_at; the results are in Instagram's order, not by time, so every page is still fetched.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 24,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 24,
              "maximum": 24,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/761168339_18330615538259673_8663040992591739350_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=104&ig_cache_key=GNOBXi3ZFqwDmR9BANb5E07iTTl4bmNDAQAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=S…",
                            "display_name": null,
                            "id": "7786451672",
                            "is_verified": false,
                            "url": "https://www.instagram.com/veganandfeastin/",
                            "username": "veganandfeastin"
                          },
                          "coauthors": [],
                          "duration_ms": 12900,
                          "hashtags": [
                            "veganpasta",
                            "tofurecipes",
                            "veganrecipes"
                          ],
                          "id": "Ddr0TPPSmMm",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 12900,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/824422121_2194005971160502_2983956026062404200_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=108&ig_cache_key=Mzk5MzUxNTUxNTA0NTM3MjcxMA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=2…",
                              "type": "video",
                              "url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t2/f2/m86/AQMLNCgISLW3dxSgrJybwxb-22qxIIioAj01cakwofcPtXdtZgIC_VI-UAa9VRGPEyMkUHLz_LtnQAo19lQCIKnr7713qLTE5q5uHRQ.mp4?_nc_cat=104&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 1080
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 160,
                            "like_count": 17516,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 438314
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": null,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-09-24T21:09:56Z",
                          "text": "silken tofu makes this linguini ridiculously creamy. an easy high protein vegan pasta that tastes way more indulgent than it actually is\n\n#veganpasta #tofurecipes #veganrecipes #easyveganmeals #veganfood",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/824422121_2194005971160502_2983956026062404200_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=108&ig_cache_key=Mzk5MzUxNTUxNTA0NTM3MjcxMA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=2…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "coauthors",
                            "mentions"
                          ],
                          "url": "https://www.instagram.com/reel/Ddr0TPPSmMm/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-19/579635209_17986846517910339_21160113348381217_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=103&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_gid=S…",
                            "display_name": null,
                            "id": "57257590338",
                            "is_verified": false,
                            "url": "https://www.instagram.com/ourhealthy_kitchen/",
                            "username": "ourhealthy_kitchen"
                          },
                          "coauthors": [],
                          "duration_ms": 29674,
                          "hashtags": [],
                          "id": "DLs0pzUy701",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 29674,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/515092177_4103543953235130_6064318765958255274_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=103&ig_cache_key=MzY2OTUzOTM2NzQyNjk2NDc4OQ%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=2…",
                              "type": "video",
                              "url": "https://scontent-atl3-1.cdninstagram.com/o1/v/t2/f2/m86/AQMlakTQEwte_5YCnwCH8oTlb1zO381trcYHZ-muqkr4Su7QGQCWQ46FHa5okk9zY_sHWTvfaRNPRpo53d-bRZw7y8nI40sDDC6mOfQ.mp4?_nc_cat=110&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 1080
                            }
                          ],
                          "mentions": [
                            "jovialfoods"
                          ],
                          "metrics": {
                            "comment_count": 215,
                            "like_count": 8552,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 206291
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": null,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2025-07-04T21:09:34Z",
                          "text": "Save this Rasta Pasta Recipe Below! 💚Wanna take a class with me?? Use the link below or in my bio to sign up to be the first to know when my next class opens! \n\nhttps://mailchi.mp/56d013b1a8c1/chefvictoriarecipes \n\nVegan + GF Rasta Pasta \nIngredients\n\n  \n6 oz dry gluten-free past…",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/515092177_4103543953235130_6064318765958255274_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=103&ig_cache_key=MzY2OTUzOTM2NzQyNjk2NDc4OQ%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=2…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "coauthors"
                          ],
                          "url": "https://www.instagram.com/reel/DLs0pzUy701/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-19/753231472_18120289603884290_3428669718987860154_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_gid…",
                            "display_name": null,
                            "id": "26583988289",
                            "is_verified": false,
                            "url": "https://www.instagram.com/lifeofagreedyvegan/",
                            "username": "lifeofagreedyvegan"
                          },
                          "coauthors": [],
                          "duration_ms": 22475,
                          "hashtags": [],
                          "id": "C3dK9xOKpNu",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 22475,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1280,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.71878-15/503216684_3619178498386054_42034667321398688_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=104&ig_cache_key=MzMwNDg0NTkyNjc2NDAyNDY4Ng%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&…",
                              "type": "video",
                              "url": "https://scontent-atl3-1.cdninstagram.com/o1/v/t2/f2/m82/AQPaJ473Q8zbT1RSqNP0R6TS7OxAUqG2Y5oCJz2wISHbGgxqqTx6jeBX-ucjwToegLLcDDSIft_Vb-TSCqGvTfdJgB62Kqxud5tAm9Y.mp4?_nc_cat=103&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 7,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": null,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2024-02-17T16:48:25Z",
                          "text": "let’s plate up one of my fav meals: homemade ✨carbonara✨\n\nrecipe 🍝🌱\n\nIngredients \n* 25g dairy-free butter (I used flora)\n* 30g all purpose flour\n* 275ml dairy-free milk (I used oat) \n* Add nutritional yeast to taste\n* 1/2 tsp garlic powder\n* 1/2 tsp smoked paprika\n* 1/2 tsp turme…",
                          "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.71878-15/503216684_3619178498386054_42034667321398688_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=104&ig_cache_key=MzMwNDg0NTkyNjc2NDAyNDY4Ng%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "coauthors",
                            "mentions"
                          ],
                          "url": "https://www.instagram.com/reel/C3dK9xOKpNu/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1281,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramSearch_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Reels matching a keyword, with plays and likes",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.search_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Instagram's ranking for the keyword (its popular page's order)",
          "page_max": 24,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/search_profiles": {
      "get": {
        "description": "Returns the Instagram accounts a web search finds for your words, like a niche, a place or a name, with their usernames and profile links. Each has its display name, bio and follower, following and post counts as the search index shows them. Add fill=true to get each account's current profile (user ID, exact counts, verified badge, picture, links) in the same response.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/search_profiles/ (Markdown: https://socialtap.dev/docs/reference/instagram/search_profiles/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/search_profiles/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/search_profiles/"
        },
        "operationId": "instagram.search_profiles.list",
        "parameters": [
          {
            "description": "Words to find Instagram accounts by, as a web search reads them: a niche, a business type, a place, a name (coffee roaster, yoga studio austin, \"blue bottle\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and intitle:, inurl: and intext: count as plain words.",
            "example": "coffee roaster",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find Instagram accounts by, as a web search reads them: a niche, a business type, a place, a name (coffee roaster, yoga studio austin, \"blue bottle\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and intitle:, inurl: and intext: count as plain words.",
              "examples": [
                "coffee roaster"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "profile.metrics.follower_count",
                            "profile.metrics.following_count",
                            "profile.metrics.post_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.instagram.com/coffeeroasterlnk/",
                          "place": null,
                          "platform": "instagram",
                          "platform_specific": {},
                          "position": 0,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "Specialty coffee, fresh roasted and made easy. Serving Lincoln and beyond since 1995. 🖤 Woman owned. Community focused.",
                            "display_name": "The Coffee Roaster",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": 4053,
                              "following_count": 1599,
                              "post_count": 1651,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://www.instagram.com/coffeeroasterlnk/",
                            "username": "coffeeroasterlnk"
                          },
                          "snippet": "4,053 followers, 1,599 following, 1,651 posts – The Coffee Roaster (@coffeeroasterlnk) on Instagram: \"Specialty coffee, fresh roasted and made easy. Serving Lincoln and beyond since 1995. 🖤 Woman owned. Community focused.\"",
                          "sound": null,
                          "title": "The Coffee Roaster (@coffeeroasterlnk) · Lincoln, NE",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/coffeeroasterlnk/"
                        },
                        {
                          "approximate_fields": [
                            "profile.metrics.follower_count",
                            "profile.metrics.following_count",
                            "profile.metrics.post_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.instagram.com/thecoffeeroaster/",
                          "place": null,
                          "platform": "instagram",
                          "platform_specific": {},
                          "position": 1,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "📍TCR Cafe NUS AS8 🎓TCR Academy 🔝Corporate Teambuilding | Trusted by Thousands ⭐️Proven Latte Art & Barista Coaching 👇Book Coffee Workshops",
                            "display_name": "The Coffee Roaster | Cafe & Coffee Academy",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": 3446,
                              "following_count": 100,
                              "post_count": 1542,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://www.instagram.com/thecoffeeroaster/",
                            "username": "thecoffeeroaster"
                          },
                          "snippet": "3,446 followers, 100 following, 1,542 posts – The Coffee Roaster | Cafe & Coffee Academy (@thecoffeeroaster) on Instagram: \"📍TCR Cafe NUS AS8 🎓TCR Academy 🔝Corporate Teambuilding | Trusted by Thousands ⭐️Proven Latte Art & Barista Coaching 👇Book Coffee Workshops\"",
                          "sound": null,
                          "title": "The Coffee Roaster | Cafe & Coffee Academy (@thecoffeeroaster) ...",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/thecoffeeroaster/"
                        },
                        {
                          "approximate_fields": [
                            "profile.metrics.follower_count",
                            "profile.metrics.following_count",
                            "profile.metrics.post_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.instagram.com/coffee_roaster_cafe/",
                          "place": null,
                          "platform": "instagram",
                          "platform_specific": {},
                          "position": 2,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "Coffee Roastery, Store and Coffee Shop. 📆 Horario: Lun a Sab de 10am a 8pm 📍 Contamos con parqueo propio",
                            "display_name": "Coffee Roaster",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": 1476,
                              "following_count": 195,
                              "post_count": 207,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://www.instagram.com/coffee_roaster_cafe/",
                            "username": "coffee_roaster_cafe"
                          },
                          "snippet": "1,476 Followers, 195 Following, 207 Posts - Coffee Roaster (@coffee_roaster_cafe) on Instagram: \"Coffee Roastery, Store and Coffee Shop. 📆 Horario: Lun a Sab de 10am a 8pm 📍 Contamos con parqueo propio\"",
                          "sound": null,
                          "title": "Coffee Roaster (@coffee_roaster_cafe) • Instagram photos and videos",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/coffee_roaster_cafe/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1168,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramSearch_profilesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Accounts by keyword, niche or place",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.search_profiles",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/search_sounds": {
      "get": {
        "description": "Returns the Instagram audio pages, songs and creators' original audio, that a web search finds for your words, with their links and titles. Each has its artist or creator, whether it's original audio, and its reel count when the search index shows it. Add fill=true to get each audio's current record (exact reel count, length, cover art, audio file, Spotify link) in the same response.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/search_sounds/ (Markdown: https://socialtap.dev/docs/reference/instagram/search_sounds/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/search_sounds/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/search_sounds/"
        },
        "operationId": "instagram.search_sounds.list",
        "parameters": [
          {
            "description": "Words to find Instagram audio by, as a web search reads them: a song, an artist, a creator, \"original audio\" and a theme (espresso sabrina carpenter, bad bunny, \"original audio\" lofi). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and intitle:, inurl: and intext: count as plain words.",
            "example": "bad bunny",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find Instagram audio by, as a web search reads them: a song, an artist, a creator, \"original audio\" and a theme (espresso sabrina carpenter, bad bunny, \"original audio\" lofi). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and intitle:, inurl: and intext: count as plain words.",
              "examples": [
                "bad bunny"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "sound.metrics.post_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.instagram.com/reels/audio/808853994575405/monaco/",
                          "place": null,
                          "platform": "instagram",
                          "platform_specific": {},
                          "position": 0,
                          "post": null,
                          "profile": null,
                          "snippet": "5M reels - Listen to Bad Bunny on Instagram and watch reels using MONACO audio",
                          "sound": {
                            "author_name": "Bad Bunny",
                            "cover_url": null,
                            "id": null,
                            "is_original": null,
                            "metrics": {
                              "post_count": 5000000
                            },
                            "title": "MONACO",
                            "url": "https://www.instagram.com/reels/audio/808853994575405/"
                          },
                          "title": "Bad Bunny | MONACO on Instagram",
                          "type": "sound",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/reels/audio/808853994575405/"
                        },
                        {
                          "approximate_fields": [
                            "sound.metrics.post_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.instagram.com/reels/audio/580872141396073/dtmf/",
                          "place": null,
                          "platform": "instagram",
                          "platform_specific": {},
                          "position": 1,
                          "post": null,
                          "profile": null,
                          "snippet": "1M reels - Listen to Bad Bunny on Instagram and watch reels using DtMF audio",
                          "sound": {
                            "author_name": "Bad Bunny",
                            "cover_url": null,
                            "id": null,
                            "is_original": null,
                            "metrics": {
                              "post_count": 1000000
                            },
                            "title": "DtMF",
                            "url": "https://www.instagram.com/reels/audio/580872141396073/"
                          },
                          "title": "Bad Bunny | DtMF on Instagram",
                          "type": "sound",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/reels/audio/580872141396073/"
                        },
                        {
                          "approximate_fields": [
                            "sound.metrics.post_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.instagram.com/reels/audio/870702934995012/la-mudanza/",
                          "place": null,
                          "platform": "instagram",
                          "platform_specific": {},
                          "position": 2,
                          "post": null,
                          "profile": null,
                          "snippet": "901K reels - Listen to Bad Bunny on Instagram and watch reels using LA MuDANZA audio",
                          "sound": {
                            "author_name": "Bad Bunny",
                            "cover_url": null,
                            "id": null,
                            "is_original": null,
                            "metrics": {
                              "post_count": 901000
                            },
                            "title": "LA MuDANZA",
                            "url": "https://www.instagram.com/reels/audio/870702934995012/"
                          },
                          "title": "Bad Bunny | LA MuDANZA on Instagram",
                          "type": "sound",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/reels/audio/870702934995012/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1142,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramSearch_soundsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Songs and original audio by name or artist",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.search_sounds",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/search_suggestions": {
      "get": {
        "description": "Returns what Instagram's search box offers logged out for a query: the account with that exact username, then matching hashtags. The account has its user ID, display name, picture and verified badge, and each hashtag its exact post count and tag ID, in Instagram's order. Send words, a username or a hashtag, in any language.\n\nReturns `{data, page, meta}`: `data` holds up to 56 `Suggestion` items (the shared schema, the same on every platform), the exact account first, then Instagram's tag search ranking. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/search_suggestions/ (Markdown: https://socialtap.dev/docs/reference/instagram/search_suggestions/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/search_suggestions/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/search_suggestions/"
        },
        "operationId": "instagram.search_suggestions.list",
        "parameters": [
          {
            "description": "What to search for, as typed into Instagram's search box: a name, a username or a word, in any language and any case (nasa, taylor swift, 料理). A leading # searches hashtags only (#cooking), a leading @ looks up the account only (@nasa).",
            "example": "nasa",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to search for, as typed into Instagram's search box: a name, a username or a word, in any language and any case (nasa, taylor swift, 料理). A leading # searches hashtags only (#cooking), a leading @ looks up the account only (@nasa).",
              "examples": [
                "nasa"
              ],
              "maxLength": 150,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 56,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 56,
              "maximum": 56,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "hashtag": null,
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "tag_id": null
                            }
                          },
                          "position": 0,
                          "profile": {
                            "avatar_url": "https://scontent-sea5-1.cdninstagram.com/v/t51.2885-19/29090066_159271188110124_1152068159029641216_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ig_cache_key=GBLhuwEsG5c225AAAAAAAADj9-wPbkULAAAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBE…",
                            "display_name": "NASA",
                            "id": "528817151",
                            "is_verified": true,
                            "url": "https://www.instagram.com/nasa/",
                            "username": "nasa"
                          },
                          "text": "nasa",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/nasa/"
                        },
                        {
                          "approximate_fields": [],
                          "hashtag": {
                            "id": "nasa",
                            "metrics": {
                              "post_count": 10161802
                            },
                            "name": "nasa",
                            "url": "https://www.instagram.com/explore/tags/nasa/"
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "tag_id": "17843701351037088"
                            }
                          },
                          "position": 1,
                          "profile": null,
                          "text": "#nasa",
                          "type": "hashtag",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/explore/tags/nasa/"
                        },
                        {
                          "approximate_fields": [],
                          "hashtag": {
                            "id": "naša",
                            "metrics": {
                              "post_count": 30513
                            },
                            "name": "naša",
                            "url": "https://www.instagram.com/explore/tags/na%C5%A1a/"
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "tag_id": "17841557482094993"
                            }
                          },
                          "position": 2,
                          "profile": null,
                          "text": "#naša",
                          "type": "hashtag",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/explore/tags/na%C5%A1a/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 391,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramSearch_suggestionsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Accounts and hashtags matching a query",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.search_suggestions",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the exact account first, then Instagram's tag search ranking",
          "page_max": 56,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "suggestion",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/similar_profiles": {
      "get": {
        "description": "Returns the accounts Instagram suggests as similar to a public profile, in its own order, from a username, profile link or user ID. Each has its user ID, username, display name, picture, verified badge, privacy and profile link. One request returns the whole suggestion list.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Profile` items (the shared schema, the same on every platform), Instagram's suggestion order. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/similar_profiles/ (Markdown: https://socialtap.dev/docs/reference/instagram/similar_profiles/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/similar_profiles/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/similar_profiles/"
        },
        "operationId": "instagram.similar_profiles.list",
        "parameters": [
          {
            "description": "Instagram username with or without the @, a numeric user ID (787132), or a profile URL (instagram.com/natgeo, m.instagram.com, instagr.am, a /related_profiles/ or /reels/ view, an instagram.com/_u/ app link). A bare number is a user ID; a number no account has as its ID is looked up as a username, and @ before digits (@2020) always means the username.",
            "example": "natgeo",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Instagram username with or without the @, a numeric user ID (787132), or a profile URL (instagram.com/natgeo, m.instagram.com, instagr.am, a /related_profiles/ or /reels/ view, an instagram.com/_u/ app link). A bare number is a user ID; a number no account has as its ID is looked up as a username, and @ before digits (@2020) always means the username.",
              "examples": [
                "natgeo"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.2885-19/93880139_247576663101568_4560165171292536832_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ss=7b68…",
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "NASA Solar System Exploration",
                          "external_links": [],
                          "id": "1611722079",
                          "is_private": false,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "account_type": null,
                              "fbid": null,
                              "is_highlights_shown": null,
                              "is_memorialized": null,
                              "is_story_live": null,
                              "pronouns": []
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.instagram.pronouns"
                          ],
                          "url": "https://www.instagram.com/nasasolarsystem/",
                          "username": "nasasolarsystem"
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-19/682869933_18586755823041127_7038301864805341036_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=100&ig_cache_key=GK3Esyhn_ltSjghCAGwXsWlBEq1hbmNDAQAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=S…",
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "National Geographic Your Shot",
                          "external_links": [],
                          "id": "1389225126",
                          "is_private": false,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "account_type": null,
                              "fbid": null,
                              "is_highlights_shown": null,
                              "is_memorialized": null,
                              "is_story_live": null,
                              "pronouns": []
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.instagram.pronouns"
                          ],
                          "url": "https://www.instagram.com/natgeoyourshot/",
                          "username": "natgeoyourshot"
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.2885-19/332350166_1219954061973263_2055192917086293201_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=103&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ss=7b…",
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "UNESCO",
                          "external_links": [],
                          "id": "36336859",
                          "is_private": false,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "account_type": null,
                              "fbid": null,
                              "is_highlights_shown": null,
                              "is_memorialized": null,
                              "is_story_live": null,
                              "pronouns": []
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.instagram.pronouns"
                          ],
                          "url": "https://www.instagram.com/unesco/",
                          "username": "unesco"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 756,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "787132",
                          "url": "https://www.instagram.com/natgeo/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramSimilar_profilesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Lookalike accounts suggested for a profile",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.similar_profiles",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Instagram's suggestion order",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/sound": {
      "get": {
        "description": "Returns an Instagram audio, a licensed song or a creator's original audio, with the exact number of reels using it, from its link or ID. You also get its title, artist and their account, length, cover art, the audio file, its Spotify link, explicit and trending flags, and for original audio when it was made and the reel it comes from.\n\nReturns `{data, meta}`: `data` is a `Sound` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/sound/ (Markdown: https://socialtap.dev/docs/reference/instagram/sound/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/sound/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/sound/"
        },
        "operationId": "instagram.sound.get",
        "parameters": [
          {
            "description": "An Instagram audio link (the audio page's instagram.com/reels/audio/822282777968975/, as a reel's audio link or the app's share sheet gives it) or the audio's numeric ID (the number in that link: a song's audio cluster or asset ID, or an original audio's ID).",
            "example": "https://www.instagram.com/reels/audio/822282777968975/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "An Instagram audio link (the audio page's instagram.com/reels/audio/822282777968975/, as a reel's audio link or the app's share sheet gives it) or the audio's numeric ID (the number in that link: a song's audio cluster or asset ID, or an original audio's ID).",
              "examples": [
                "https://www.instagram.com/reels/audio/822282777968975/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author_name": "BTS",
                        "authors": [
                          {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/749652868_18576613621075834_3305084378993563391_n.jpg?stp=dst-jpg_s150x150_tt6&efg=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_cat=1&_nc_oc=SCRUBBED&_nc_ohc=SCRUBBED&_nc_gid=SCRUBBED&edm=SCRUBBED&ccb=SCRUBBED&oh=SCR…",
                            "display_name": "BTS official",
                            "id": "2274763833",
                            "is_verified": true,
                            "url": "https://www.instagram.com/bts.bighitofficial/",
                            "username": "bts.bighitofficial"
                          }
                        ],
                        "cover_url": "https://scontent-atl3-2.xx.fbcdn.net/v/t39.30808-6/425756227_90027415521163_4181206696607213053_n.jpg?stp=dst-jpg_p526x296_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-atl3-2.xx&_nc_gid=SCRUBBED&_nc_ss=7b689&oh=SCRUBBED&oe…",
                        "duration_ms": 231859,
                        "id": "822282777968975",
                        "is_original": false,
                        "metrics": {
                          "post_count": 14305
                        },
                        "platform": "instagram",
                        "platform_specific": {
                          "instagram": {
                            "asset_id": "253176454123690",
                            "created_at": null,
                            "is_explicit": false,
                            "is_lyrics_shown": true,
                            "is_trending": false,
                            "source_post": null
                          }
                        },
                        "play_url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t2/f2/m69/AQPgiSJyoc_dPI9Ax2JiCvLJXX2L2GgcIavzdneCJUUaTiuIWF_hjtybu9_eoeJwWUaWGOhSKsS-7SdYN1bakLs7.mp4?strext=1&_nc_cat=1&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=SCRUBBED&…",
                        "streaming_links": [
                          {
                            "service": "spotify",
                            "url": "https://open.spotify.com/track/3wyrhwPpV8uhMMEms4vG3X"
                          }
                        ],
                        "title": "Not Today",
                        "unknown_fields": [],
                        "url": "https://www.instagram.com/reels/audio/822282777968975/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 898,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "sound",
                          "id": "822282777968975",
                          "url": "https://www.instagram.com/reels/audio/822282777968975/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramSoundResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Song or original audio with its reel count",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.sound",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "sound",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/sound_posts": {
      "get": {
        "description": "Returns the public Instagram reels that use a song or original audio, in Instagram's own order, from the audio's link or ID. Each has its caption, hashtags, mentions, collaborators, publish time, length, video and cover, author, and exact play, like and comment counts.\n\nReturns `{data, page, meta}`: `data` holds up to 12 `Post` items (the shared schema, the same on every platform), Instagram's ranking of the audio's reels (the order its audio page shows). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/sound_posts/ (Markdown: https://socialtap.dev/docs/reference/instagram/sound_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/sound_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/sound_posts/"
        },
        "operationId": "instagram.sound_posts.list",
        "parameters": [
          {
            "description": "An Instagram audio link (the audio page's instagram.com/reels/audio/822282777968975/, as a reel's audio link or the app's share sheet gives it) or the audio's numeric ID (the number in that link: a song's audio cluster or asset ID, or an original audio's ID).",
            "example": "https://www.instagram.com/reels/audio/822282777968975/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "An Instagram audio link (the audio page's instagram.com/reels/audio/822282777968975/, as a reel's audio link or the app's share sheet gives it) or the audio's numeric ID (the number in that link: a song's audio cluster or asset ID, or an original audio's ID).",
              "examples": [
                "https://www.instagram.com/reels/audio/822282777968975/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 12,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 12,
              "maximum": 12,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/749652868_18576613621075834_3305084378993563391_n.jpg?stp=dst-jpg_s150x150_tt6&efg=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_cat=1&_nc_oc=SCRUBBED&_nc_ohc=SCRUBBED&_nc_gid=SCRUBBED&edm=SCRUBBED&ccb=SCRUBBED&oh=SCR…",
                            "display_name": "BTS official",
                            "id": "2274763833",
                            "is_verified": true,
                            "url": "https://www.instagram.com/bts.bighitofficial/",
                            "username": "bts.bighitofficial"
                          },
                          "coauthors": [],
                          "duration_ms": 47583,
                          "hashtags": [
                            "BTS",
                            "방탄소년단",
                            "BTS_WORLDTOUR_ARIRANG"
                          ],
                          "id": "DdY6xztBLZr",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 47583,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/813817767_18592910803075834_2435059816000399444_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=109&ig_cache_key=Mzk4ODE5NTk3OTUwNDY5NDg5MTE4NTkyOTEwODAwMDc1ODM0.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                              "type": "video",
                              "url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t2/f2/m86/AQNSWjEUWtQ_qqGAUcZtYjqsQVpiWY8QsO6Mt2hT_irw02tPY8xx9UUyt_0wHYaxa9QfnYEvxFMyQSwaUccDDSppN8H4iOBqaR0ujow.mp4?_nc_cat=101&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 1080
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 17547,
                            "like_count": 1960365,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 19625255
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": false,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-09-17T13:00:03Z",
                          "text": "BTS WORLD TOUR ‘ARIRANG’ LIVE VIEWING FROM BUENOS AIRES & SÃO PAULO\nCelebrate the finale of the Latin America tour in cinemas!\n\n🎬 Live from Argentina October 24, and Brazil October 30*\n*Broadcasts in some territories are scheduled later to accommodate local time zones.\n\n#BTS #방탄소…",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/813817767_18592910803075834_2435059816000399444_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=109&ig_cache_key=Mzk4ODE5NTk3OTUwNDY5NDg5MTE4NTkyOTEwODAwMDc1ODM0.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/reel/DdY6xztBLZr/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/693554212_18209827891330660_6621435266931921089_n.jpg?stp=dst-jpg_s150x150_tt6&efg=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_cat=104&_nc_oc=SCRUBBED&_nc_ohc=SCRUBBED&_nc_gid=SCRUBBED&edm=SCRUBBED&ccb=SCRUBBED&oh=S…",
                            "display_name": "Música Entrelíneas",
                            "id": "9976858659",
                            "is_verified": false,
                            "url": "https://www.instagram.com/musicaentrelineas_/",
                            "username": "musicaentrelineas_"
                          },
                          "coauthors": [],
                          "duration_ms": 28833,
                          "hashtags": [
                            "BTSNotToday",
                            "armybtsfans",
                            "youneverwalkalonebts"
                          ],
                          "id": "DehPYMqABST",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 28833,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 684,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/849745634_18228394561330660_4334229251781734573_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=101&ig_cache_key=NDAwODU1Mjc3Njg5MTExMDU0NzE4MjI4Mzk0NTU1MzMwNjYw.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                              "type": "video",
                              "url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t2/f2/m86/AQPYdZPGj1tDySyhbllS70jhBBOgd9wcbIjUDIfgfWOsSJIaKR8vCW4n_6RS7ubziJn5eyK_O3vMgkcGNL4ZoMungYRfAT7AH1QmV08.mp4?_nc_cat=102&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 1280
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 3,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": false,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-10-15T15:06:14Z",
                          "text": "📅 Lanzada el 13 de febrero de 2017, ”Not Today” de BT formó parte del álbum You Never Walk Alone, la reedición de WINGS, y fue uno de los sencillos principales del proyecto junto a “Spring Day”. \n\n🎬 El videoclip se estrenó a través del canal oficial de YouTube de Big Hit Entertai…",
                          "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/849745634_18228394561330660_4334229251781734573_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=101&ig_cache_key=NDAwODU1Mjc3Njg5MTExMDU0NzE4MjI4Mzk0NTU1MzMwNjYw.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/reel/DehPYMqABST/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/859316134_18112282658068468_4599673650844066402_n.jpg?stp=dst-jpg_s150x150_tt6&efg=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_cat=104&_nc_oc=SCRUBBED&_nc_ohc=SCRUBBED&_nc_gid=SCRUBBED&edm=SCRUBBED&ccb=SCRUBBED&oh=S…",
                            "display_name": "@bts_ lyrics_song....",
                            "id": "32003876467",
                            "is_verified": false,
                            "url": "https://www.instagram.com/bts_lyrics_song_19/",
                            "username": "bts_lyrics_song_19"
                          },
                          "coauthors": [],
                          "duration_ms": 18878,
                          "hashtags": [
                            "btsarmy",
                            "bangtan",
                            "btslyrics"
                          ],
                          "id": "Deov07vSo6m",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 18878,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1280,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/855904611_993119610496656_1172092764080329878_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=110&ig_cache_key=NDAxMDY2NTgxMzkxNjQyMTc5OA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23…",
                              "type": "video",
                              "url": "https://scontent-atl3-1.cdninstagram.com/o1/v/t2/f2/m86/AQMtNynnsL1T0bcraO9SVS9tnR8o7DA__iJ8kXvVr3eLP1vD-mOSQq0EJ3NAG1w9W_kEkmEq7HZ8MtmN1Ht_hCXAAjGPDO7LtJ3-RvA.mp4?_nc_cat=109&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 0,
                            "like_count": 29,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 712
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": false,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-10-18T13:05:12Z",
                          "text": "Who is your favorite line comment me🫰🏻😊#btsarmy #bangtan #btslyrics #bts #mnijungkook🎶💜🎀✨️",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/855904611_993119610496656_1172092764080329878_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=110&ig_cache_key=NDAxMDY2NTgxMzkxNjQyMTc5OA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.instagram.com/reel/Deov07vSo6m/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1001,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "sound",
                          "id": "822282777968975",
                          "url": "https://www.instagram.com/reels/audio/822282777968975/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramSound_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Reels that use a song or original audio",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.sound_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Instagram's ranking of the audio's reels (the order its audio page shows)",
          "page_max": 12,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/story": {
      "get": {
        "description": "Returns a public Instagram story's image or video link, at the best quality Instagram serves, from the story's link or a highlight item's link. You also get its cover, size, length, author, publish time and, for videos, the view count.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/story/ (Markdown: https://socialtap.dev/docs/reference/instagram/story/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/story/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/story/"
        },
        "operationId": "instagram.story.get",
        "parameters": [
          {
            "description": "Instagram story URL: a story's own link (instagram.com/stories/<username>/<story id>/, as the app shares it) or a highlight's item (instagram.com/stories/highlights/<highlight id>/?story_media_id=<story id>_<user id>, or the highlight share link instagram.com/s/…?story_media_id=…). m.instagram.com links and tracking params are accepted.",
            "example": "https://www.instagram.com/stories/highlights/18023864549864045/?story_media_id=4012120567117354624_787132",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Instagram story URL: a story's own link (instagram.com/stories/<username>/<story id>/, as the app shares it) or a highlight's item (instagram.com/stories/highlights/<highlight id>/?story_media_id=<story id>_<user id>, or the highlight share link instagram.com/s/…?story_media_id=…). m.instagram.com links and tracking params are accepted.",
              "examples": [
                "https://www.instagram.com/stories/highlights/18023864549864045/?story_media_id=4012120567117354624_787132"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/683576066_18653628823019133_9051036240972105113_n.jpg?stp=dst-jpg_s150x150_tt6&efg=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_cat=1&_nc_oc=SCRUBBED&_nc_ohc=SCRUBBED&_nc_gid=SCRUBBED&edm=SCRUBBED&ccb=SCRUBBED&oh=SCR…",
                          "display_name": null,
                          "id": "787132",
                          "is_verified": true,
                          "url": "https://www.instagram.com/natgeo/",
                          "username": "natgeo"
                        },
                        "coauthors": [],
                        "duration_ms": 9943,
                        "hashtags": [],
                        "id": "4012120567117354624",
                        "is_nsfw": null,
                        "is_pinned": null,
                        "is_sponsored": false,
                        "language": null,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": 9943,
                            "expires_at": "2026-10-25T18:00:00Z",
                            "height": 1280,
                            "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/858981307_2584622395349397_7318871625928867813_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=106&ig_cache_key=NDAxMjEyMDU2NzExNzM1NDYyNA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=2…",
                            "type": "video",
                            "url": "https://scontent-atl3-1.cdninstagram.com/o1/v/t2/f2/m78/AQPyy1nSmXOn73Q1QB0NVznCvo1RmXxggQMktLVDCIUMzEKO_6-0Qil9pON54uB0l9mHyflRzzzRAJIhXoDdyiKX2f5h01zsvcDNEWk.mp4?_nc_cat=100&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                            "width": 720
                          }
                        ],
                        "mentions": [],
                        "metrics": {
                          "comment_count": null,
                          "like_count": null,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": null,
                          "share_count": null,
                          "view_count": null
                        },
                        "platform": "instagram",
                        "platform_specific": {
                          "instagram": {
                            "is_ai_generated": false,
                            "link": null,
                            "location": null
                          }
                        },
                        "platform_type": "story",
                        "published_at": "2026-10-20T13:14:30Z",
                        "text": null,
                        "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/858981307_2584622395349397_7318871625928867813_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=106&ig_cache_key=NDAxMjEyMDU2NzExNzM1NDYyNA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=2…",
                        "title": null,
                        "type": "video",
                        "unknown_fields": [],
                        "url": "https://www.instagram.com/stories/natgeo/4012120567117354624/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 464,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "story",
                          "id": "4012120567117354624",
                          "url": "https://www.instagram.com/stories/natgeo/4012120567117354624/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramStoryResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Image or video file, from the story's link",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.story",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/topic": {
      "get": {
        "description": "Returns an Instagram topic, the public page Instagram publishes for a search keyword, from its link, a hashtag link or its words. You get its title, Instagram's generated summary with the web pages it cites, the related searches Instagram suggests and how many reels it counts.\n\nReturns `{data, meta}`: `data` is a `Topic` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/topic/ (Markdown: https://socialtap.dev/docs/reference/instagram/topic/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/topic/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/topic/"
        },
        "operationId": "instagram.topic.get",
        "parameters": [
          {
            "description": "An Instagram topic page link (instagram.com/popular/harry-potter/), a hashtag link (instagram.com/explore/tags/cooking/, which opens its topic page for signed-out visitors), a keyword search link (instagram.com/explore/search/keyword/?q=harry%20potter), or the topic's words (harry potter). Matched as Instagram keys its pages: case, a leading # or @ and hyphens are ignored.",
            "example": "https://www.instagram.com/popular/harry-potter/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "An Instagram topic page link (instagram.com/popular/harry-potter/), a hashtag link (instagram.com/explore/tags/cooking/, which opens its topic page for signed-out visitors), a keyword search link (instagram.com/explore/search/keyword/?q=harry%20potter), or the topic's words (harry potter). Matched as Instagram keys its pages: case, a leading # or @ and hyphens are ignored.",
              "examples": [
                "https://www.instagram.com/popular/harry-potter/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "platform_specific.instagram.post_count"
                        ],
                        "description": "Harry Potter (harrypotter), the official franchise account, recently announced the HBO Original Series premiere of Harry Potter and the Philosopher’s Stone for December 25 on HBO Max. The page shared a first-look poster of Dominic McLaughlin as Harry, with Hogwarts reflected in h…",
                        "id": "harry-potter",
                        "name": "Harry Potter",
                        "platform": "instagram",
                        "platform_specific": {
                          "instagram": {
                            "is_category": false,
                            "post_count": 189000000,
                            "source_urls": [
                              "https://www.businesstoday.in/amp/trending/entertainment/story/harry-potter-returns-to-screens-this-christmas-hbo-unveils-first-look-at-new-series-564654-2026-10-30",
                              "https://www.thestatesman.com/entertainment/meet-the-new-harry-potter-cast-harry-parents-and-charlie-weasley-are-officially-set-for-hbo-christmas-premiere-1503655977.html",
                              "https://www.theweek.in/news/entertainment/2026/10/30/harry-potter-hbo-series-jiohotstar-india-release.html"
                            ]
                          }
                        },
                        "related_searches": [
                          "copo harry potter cacau show",
                          "harry potter hbo behind the scenes",
                          "jamie campbell bower harry potter"
                        ],
                        "unknown_fields": [],
                        "url": "https://www.instagram.com/popular/harry-potter/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1263,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "topic",
                          "id": "harry-potter",
                          "url": "https://www.instagram.com/popular/harry-potter/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramTopicResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Generated summary, related searches and reel count",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.topic",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "topic",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/transcript": {
      "get": {
        "description": "Returns the timed transcript of a public Instagram reel or video post, from its link or shortcode. Instagram shows no captions logged out, so most transcripts are speech-to-text on the post's audio. Each segment has its start and end time, and text holds the whole transcript. For a carousel, img_index picks the video.\n\nReturns `{data, meta}`: `data` is a `Transcript` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit (captions) or 2 credits + 2 per started minute of media (speech-to-text) per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/transcript/ (Markdown: https://socialtap.dev/docs/reference/instagram/transcript/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/transcript/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/transcript/"
        },
        "operationId": "instagram.transcript.get",
        "parameters": [
          {
            "description": "Instagram reel/post URL (instagram.com/reel/…, /reels/…, /p/…, /tv/…, instagr.am, instagram.com/share/… links) or a raw shortcode. For carousel posts, ?img_index=N selects the item; default is the first video.",
            "example": "https://www.instagram.com/p/De1S3KpCXf0/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Instagram reel/post URL (instagram.com/reel/…, /reels/…, /p/…, /tv/…, instagr.am, instagram.com/share/… links) or a raw shortcode. For carousel posts, ?img_index=N selects the item; default is the first video.",
              "examples": [
                "https://www.instagram.com/reel/De1S3KpCXf0/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "available_languages": [],
                        "duration_ms": 23745,
                        "id": "De1S3KpCXf0",
                        "is_auto_generated": true,
                        "language": "en",
                        "platform": "instagram",
                        "platform_specific": {},
                        "segments": [
                          {
                            "end_ms": 3580,
                            "start_ms": 0,
                            "text": "You are looking at nudibranchs. You ever seen anything that crazy looking?"
                          },
                          {
                            "end_ms": 9220,
                            "start_ms": 3800,
                            "text": "Every color in the rainbow. These are marine snails basically that have lost their shells"
                          },
                          {
                            "end_ms": 13480,
                            "start_ms": 9220,
                            "text": "over time and developed these elaborate colors. Usually brightly colored animals are toxic."
                          }
                        ],
                        "source": "asr",
                        "text": "You are looking at nudibranchs. You ever seen anything that crazy looking? Every color in the rainbow. These are marine snails basically that have lost their shells over time and developed these elaborate colors. Usually brightly colored animals are toxic. Some of these are, some…",
                        "url": "https://www.instagram.com/reel/De1S3KpCXf0/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "asr",
                        "is_cached": false,
                        "credits_charged": 4,
                        "latency_ms": 4329,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "De1S3KpCXf0",
                          "url": "https://www.instagram.com/reel/De1S3KpCXf0/"
                        },
                        "credits_remaining": 9996,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramTranscriptResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "no_transcript": {
                    "$ref": "#/components/examples/no_transcript"
                  },
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.\n\n`no_transcript`: The video or audio exists but has no transcript: no caption track and no speech to transcribe. Do not retry. If the platform offers other languages, try one with lang.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Timed transcript of a public reel or video",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.transcript",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 122,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "captions"
            },
            {
              "credits": 2,
              "label": "2 credits + 2 per started minute of media",
              "max": 122,
              "per": 2,
              "source": "asr",
              "unit": "media_minute",
              "unit_max": 60
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "transcript",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/trending_posts": {
      "get": {
        "description": "Returns the reels Instagram's Reels tab shows a logged-out visitor right now, with a fresh batch on each first page. Each has its link, caption, hashtags, mentions, publish time, author, like and comment counts, length, size, cover and video file.\n\nReturns `{data, page, meta}`: `data` holds up to 40 `Post` items (the shared schema, the same on every platform), Instagram's reels feed order (a fresh selection on each first page). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/trending_posts/ (Markdown: https://socialtap.dev/docs/reference/instagram/trending_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/trending_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/trending_posts/"
        },
        "operationId": "instagram.trending_posts.list",
        "parameters": [
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Filters each page by published_at; the feed is in Instagram's order, not by time, so every page is still fetched.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Filters each page by published_at; the feed is in Instagram's order, not by time, so every page is still fetched.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 40,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 40,
              "maximum": 40,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/553367442_18526794646057326_7898955892857492825_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=S…",
                            "display_name": null,
                            "id": "229753325",
                            "is_verified": null,
                            "url": "https://www.instagram.com/timjdillon/",
                            "username": "timjdillon"
                          },
                          "coauthors": [],
                          "duration_ms": 47067,
                          "hashtags": [],
                          "id": "DfKXhH2xZGc",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 47067,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/876556304_1066808916349952_6134937113782217150_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=108&ig_cache_key=NDAyMDEyOTA0ODYyOTE4Njk3MjEwNjY4MDg5MTMwMTY2MTk%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc…",
                              "type": "video",
                              "url": "https://scontent-atl3-1.cdninstagram.com/o1/v/t2/f2/m86/AQNq6Fa5uFHJFrqjX5H5azRqMlPEXic7cv3A6bb-eeq-vyYlmoO9e4cb_u3eagtvGMHyL7Dy-2VRQVKCFItb1KqPQHvGcZkBb8LL1_0.mp4?_nc_cat=108&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 1080
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 1636,
                            "like_count": 66668,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": null,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-10-31T14:27:15Z",
                          "text": "New episode out today at 12 noon. 🎃🎃🎃",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/876556304_1066808916349952_6134937113782217150_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=108&ig_cache_key=NDAyMDEyOTA0ODYyOTE4Njk3MjEwNjY4MDg5MTMwMTY2MTk%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "coauthors",
                            "mentions"
                          ],
                          "url": "https://www.instagram.com/reel/DfKXhH2xZGc/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.2885-19/66401604_490669885085166_8971698300612771840_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ss=7b689&…",
                            "display_name": null,
                            "id": "1311602026",
                            "is_verified": null,
                            "url": "https://www.instagram.com/suburban_prince/",
                            "username": "suburban_prince"
                          },
                          "coauthors": [],
                          "duration_ms": 57120,
                          "hashtags": [],
                          "id": "DfIizPaSPCb",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 57120,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 2560,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/874466886_1676249104058201_2716064828296650486_n.jpg?stp=dst-jpegr_e15_tt6&_nc_cat=108&ig_cache_key=NDAxOTYxNTcyMjI0OTk3MzkxNTExMjQxODIxMTA1NDEzODg%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_…",
                              "type": "video",
                              "url": "https://scontent-atl3-1.cdninstagram.com/o1/v/t16/f2/m84/AQPvrSZPtYAtPtTTBXfoYIr3MNu9zQAiDLqH3pwswoAA-GveiM_uz947YYWZrT4LivNq9tVcrpP-LH1Qbiewb64ftwV-KXBqd7lUYDo.mp4?_nc_cat=108&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=…",
                              "width": 1440
                            }
                          ],
                          "mentions": [
                            "700creditedwin"
                          ],
                          "metrics": {
                            "comment_count": 2547,
                            "like_count": 177783,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": null,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-10-30T21:27:06Z",
                          "text": "@700creditedwin",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/874466886_1676249104058201_2716064828296650486_n.jpg?stp=dst-jpegr_e15_tt6&_nc_cat=108&ig_cache_key=NDAxOTYxNTcyMjI0OTk3MzkxNTExMjQxODIxMTA1NDEzODg%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "coauthors"
                          ],
                          "url": "https://www.instagram.com/reel/DfIizPaSPCb/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/579682655_18537208666023480_440396525652691733_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=105&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=…",
                            "display_name": null,
                            "id": "41495479",
                            "is_verified": null,
                            "url": "https://www.instagram.com/nakkiagold/",
                            "username": "nakkiagold"
                          },
                          "coauthors": [],
                          "duration_ms": 122136,
                          "hashtags": [],
                          "id": "DfBMmcnpSIO",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 122136,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 854,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/870167702_18639152566023480_8900343708547536273_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=109&ig_cache_key=NDAxNzU0Nzc2MTIxOTM0Njk1ODE4NjM5MTUyNTYzMDIzNDgw.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                              "type": "video",
                              "url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t2/f2/m86/AQPlfIWHtV0agduy_sxdh4bqKUit09uG4iMz8E96rAB-_fGN9LDwnUYqgJFCGMRfI2Nij1BAwKar1wRuEDuziuRW_mHVARS4Ls_kghs.mp4?_nc_cat=104&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
                              "width": 480
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 22609,
                            "like_count": 174412,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "instagram",
                          "platform_specific": {
                            "instagram": {
                              "is_ai_generated": null,
                              "link": null,
                              "location": null
                            }
                          },
                          "platform_type": "reel",
                          "published_at": "2026-10-28T01:04:16Z",
                          "text": "When all the Wives show up to the funeral 👀 I guess the MAIN one the only one who got up to speak! 📍",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/870167702_18639152566023480_8900343708547536273_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=109&ig_cache_key=NDAxNzU0Nzc2MTIxOTM0Njk1ODE4NjM5MTUyNTYzMDIzNDgw.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "coauthors",
                            "mentions"
                          ],
                          "url": "https://www.instagram.com/reel/DfBMmcnpSIO/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 996,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramTrending_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Recommended reels, a fresh batch each time",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.trending_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Instagram's reels feed order (a fresh selection on each first page)",
          "page_max": 40,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/instagram/username": {
      "get": {
        "description": "Checks whether an Instagram username can be registered now, the way the sign-up form does, from a username or profile link. When it can't, you get why (taken or reserved, or against Instagram's username rules, in Instagram's words) and the free usernames the form suggests instead, in its order.\n\nReturns `{data, meta}`: `data` is a `Username` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/instagram/username/ (Markdown: https://socialtap.dev/docs/reference/instagram/username/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/instagram/username/index.md)",
          "url": "https://socialtap.dev/docs/reference/instagram/username/"
        },
        "operationId": "instagram.username.get",
        "parameters": [
          {
            "description": "The Instagram username to check, with or without the @ (socialtap, @socialtap), or a profile link (instagram.com/socialtap). Usernames are case-insensitive: the check is of the lowercase name.",
            "example": "socialtap",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Instagram username to check, with or without the @ (socialtap, @socialtap), or a profile link (instagram.com/socialtap). Usernames are case-insensitive: the check is of the lowercase name.",
              "examples": [
                "socialtap"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "id": "socialtap",
                        "is_available": false,
                        "message": "The username socialtap is not available.",
                        "platform": "instagram",
                        "platform_specific": {},
                        "reason": "taken",
                        "suggestions": [
                          "soci.altap",
                          "socia_ltap",
                          "soci_altap"
                        ],
                        "url": "https://www.instagram.com/socialtap/",
                        "username": "socialtap"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "instagram",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 608,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "socialtap",
                          "url": "https://www.instagram.com/socialtap/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/InstagramUsernameResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Free or taken, with suggested alternatives",
        "tags": [
          "Instagram"
        ],
        "x-socialtap-endpoint": "instagram.username",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "username",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/invitations": {
      "get": {
        "description": "The account's pending invitations, newest first. Free.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "invitations.list",
        "parameters": [
          {
            "description": "Invitations per page (default and maximum 100).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "created_at": {
                            "description": "When it was last sent, RFC 3339 UTC.",
                            "format": "date-time",
                            "type": "string"
                          },
                          "email": {
                            "description": "The address invited: only a person signed in with this verified address can accept.",
                            "type": "string"
                          },
                          "expires_at": {
                            "description": "When its link stops working, RFC 3339 UTC.",
                            "format": "date-time",
                            "type": "string"
                          },
                          "id": {
                            "description": "Invitation ID (inv_…).",
                            "type": "string"
                          },
                          "invited_by": {
                            "description": "The address of the person who sent it; null when they are no longer a person here.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "object": {
                            "description": "Always invitation.",
                            "enum": [
                              "invitation"
                            ],
                            "type": "string"
                          },
                          "role": {
                            "description": "The role they get when they accept.",
                            "enum": [
                              "admin",
                              "member"
                            ],
                            "type": "string"
                          },
                          "status": {
                            "description": "pending: its link works until expires_at. New values may be added.",
                            "enum": [
                              "pending",
                              "accepted",
                              "revoked",
                              "expired"
                            ],
                            "type": "string"
                          }
                        },
                        "required": [
                          "object",
                          "id",
                          "email",
                          "role",
                          "status",
                          "invited_by",
                          "created_at",
                          "expires_at"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List invitations waiting to be accepted",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "List invitations waiting to be accepted",
        "tags": [
          "Team"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "admin",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "post": {
        "description": "Emails a link to join with a role: it works once, for `invitation_ttl_s` (7 days), for a person signed in with that verified address (inviting it again re-sends it). Per account: `max_members` (50) people, `max_open_invitations` (25) waiting, `invitations_per_day` (25) emails a day. Free.\n\n**Auth:** the dashboard session cookie.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "invitations.create",
        "parameters": [
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "email": {
                    "description": "Who to invite. Inviting an address that has an invitation waiting sends it again, with a new link and this role.",
                    "maxLength": 254,
                    "minLength": 3,
                    "type": "string"
                  },
                  "role": {
                    "description": "The role they get. Default: member.",
                    "enum": [
                      "admin",
                      "member"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "email"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "created_at": {
                          "description": "When it was last sent, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "email": {
                          "description": "The address invited: only a person signed in with this verified address can accept.",
                          "type": "string"
                        },
                        "expires_at": {
                          "description": "When its link stops working, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "id": {
                          "description": "Invitation ID (inv_…).",
                          "type": "string"
                        },
                        "invited_by": {
                          "description": "The address of the person who sent it; null when they are no longer a person here.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "object": {
                          "description": "Always invitation.",
                          "enum": [
                            "invitation"
                          ],
                          "type": "string"
                        },
                        "role": {
                          "description": "The role they get when they accept.",
                          "enum": [
                            "admin",
                            "member"
                          ],
                          "type": "string"
                        },
                        "status": {
                          "description": "pending: its link works until expires_at. New values may be added.",
                          "enum": [
                            "pending",
                            "accepted",
                            "revoked",
                            "expired"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "email",
                        "role",
                        "status",
                        "invited_by",
                        "created_at",
                        "expires_at"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Invite someone by email",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Invite someone by email",
        "tags": [
          "Team"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/invitations/accept": {
      "post": {
        "description": "Joins the invitation's account with its role, as the signed-in person, whose verified address must be the one invited. Free.\n\n**Auth:** the dashboard session cookie.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "invitations.accept",
        "parameters": [
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "token": {
                    "description": "The invitation's token (after # in the emailed link).",
                    "maxLength": 200,
                    "minLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "token"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "account_id": {
                          "description": "The account (acct_…): send it as x-account-id to act on it.",
                          "type": "string"
                        },
                        "deletes_at": {
                          "description": "When the account is deleted for good, RFC 3339 UTC: its owner asked to delete it, and starting the dashboard on it (POST /v1/session with x-account-id) cancels that. null when it isn't being deleted.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "joined_at": {
                          "description": "When they joined it, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always account_membership.",
                          "enum": [
                            "account_membership"
                          ],
                          "type": "string"
                        },
                        "owner_email": {
                          "description": "Its owner's address, which names it.",
                          "type": "string"
                        },
                        "role": {
                          "description": "The person's role in it.",
                          "enum": [
                            "owner",
                            "admin",
                            "member"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "account_id",
                        "owner_email",
                        "role",
                        "joined_at",
                        "deletes_at"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Accept an invitation",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Accept an invitation",
        "tags": [
          "Team"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/invitations/{id}": {
      "delete": {
        "description": "Its link stops working at once. Free.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "invitations.revoke",
        "parameters": [
          {
            "description": "Invitation ID (inv_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "created_at": {
                          "description": "When it was last sent, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "email": {
                          "description": "The address invited: only a person signed in with this verified address can accept.",
                          "type": "string"
                        },
                        "expires_at": {
                          "description": "When its link stops working, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "id": {
                          "description": "Invitation ID (inv_…).",
                          "type": "string"
                        },
                        "invited_by": {
                          "description": "The address of the person who sent it; null when they are no longer a person here.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "object": {
                          "description": "Always invitation.",
                          "enum": [
                            "invitation"
                          ],
                          "type": "string"
                        },
                        "role": {
                          "description": "The role they get when they accept.",
                          "enum": [
                            "admin",
                            "member"
                          ],
                          "type": "string"
                        },
                        "status": {
                          "description": "pending: its link works until expires_at. New values may be added.",
                          "enum": [
                            "pending",
                            "accepted",
                            "revoked",
                            "expired"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "email",
                        "role",
                        "status",
                        "invited_by",
                        "created_at",
                        "expires_at"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Revoke an invitation",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Revoke an invitation",
        "tags": [
          "Team"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/jobs": {
      "get": {
        "description": "The account's jobs, newest first, cursor-paged. Records are kept `records_retention_s` (30 days) after a job ends. Free.\n\n**Auth:** an API key with the `jobs:read` scope, or the dashboard session.",
        "operationId": "jobs.list",
        "parameters": [
          {
            "description": "Only jobs in this status.",
            "in": "query",
            "name": "status",
            "schema": {
              "enum": [
                "queued",
                "running",
                "canceling",
                "completed",
                "canceled",
                "expired"
              ],
              "type": "string"
            }
          },
          {
            "description": "Jobs per page (default and maximum 100).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page; omit to start from the newest.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "cancel_requested_at": {
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "created_at": {
                            "format": "date-time",
                            "type": "string"
                          },
                          "credits": {
                            "properties": {
                              "charged": {
                                "description": "Credits charged so far, each page once (items' prices; failed items are free).",
                                "type": "integer"
                              },
                              "max": {
                                "description": "max_credits: the most the job may spend.",
                                "type": "integer"
                              },
                              "reserved": {
                                "description": "Credits its running pages may still use (0 once the job ends).",
                                "type": "integer"
                              }
                            },
                            "required": [
                              "max",
                              "reserved",
                              "charged"
                            ],
                            "type": "object"
                          },
                          "expires_at": {
                            "description": "The deadline: items not ended by then expire.",
                            "format": "date-time",
                            "type": "string"
                          },
                          "finished_at": {
                            "description": "When the job ended; null while it runs.",
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "id": {
                            "description": "The job ID (job_…).",
                            "type": "string"
                          },
                          "max_age": {
                            "description": "The job's max_age; null when it accepts no cached results.",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "metadata": {
                            "additionalProperties": {
                              "type": "string"
                            },
                            "description": "Your metadata; {} when none.",
                            "type": "object"
                          },
                          "object": {
                            "description": "Always job.",
                            "enum": [
                              "job"
                            ],
                            "type": "string"
                          },
                          "request_counts": {
                            "properties": {
                              "canceled": {
                                "type": "integer"
                              },
                              "expired": {
                                "type": "integer"
                              },
                              "failed": {
                                "type": "integer"
                              },
                              "queued": {
                                "description": "Not started.",
                                "type": "integer"
                              },
                              "running": {
                                "description": "Started (fetching, waiting for a retry or walking pages).",
                                "type": "integer"
                              },
                              "succeeded": {
                                "type": "integer"
                              },
                              "total": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "total",
                              "queued",
                              "running",
                              "succeeded",
                              "failed",
                              "canceled",
                              "expired"
                            ],
                            "type": "object"
                          },
                          "results_expire_at": {
                            "description": "When results are deleted; null while the job runs.",
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "results_url": {
                            "description": "Every result as JSON Lines (one JobResult per line), signed: works without the API key until results_url_expires_at. Null until the job ends and after results_expire_at.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "results_url_expires_at": {
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "started_at": {
                            "description": "When the first item started; null before.",
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "description": "queued: nothing started yet. running. canceling: canceled, running items finishing. completed: every item ended (check request_counts: there is no job-level failure). canceled. expired: the deadline passed; unfinished items expired.",
                            "enum": [
                              "queued",
                              "running",
                              "canceling",
                              "completed",
                              "canceled",
                              "expired"
                            ],
                            "type": "string"
                          },
                          "webhook_url": {
                            "description": "The job's own webhook URL; null when none.",
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "object",
                          "id",
                          "status",
                          "request_counts",
                          "credits",
                          "max_age",
                          "metadata",
                          "webhook_url",
                          "created_at",
                          "started_at",
                          "finished_at",
                          "cancel_requested_at",
                          "expires_at",
                          "results_url",
                          "results_url_expires_at",
                          "results_expire_at"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List jobs, newest first",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "List jobs, newest first",
        "tags": [
          "Jobs"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "member",
          "scope": "jobs:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "post": {
        "description": "Runs up to `max_requests` (1000) endpoint requests in the background: each item is exactly the request its endpoint answers synchronously, at the same price (failed items are free), with the same caches. `max_pages` walks a list endpoint server-side with its cursor. Credits work as for synchronous requests: each page reserves its endpoint's minimum when it runs (against the balance and the calling key's spend limit) and is topped up to its price, so a job starts whenever its first page could run; `max_credits` (default: the sum of every item's maximum price) caps what the job may spend. With `wait`, the answer is 200 with the first page of results when the job ends in time (a synchronous batch), else 202 with the job; poll `GET /v1/jobs/{id}` (free) or subscribe to `job.completed`.\n\n**Auth:** an API key with the `jobs` scope.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "jobs.create",
        "parameters": [
          {
            "description": "Seconds to wait for the job to end before answering. If it ends in time the answer is 200 with the first page of results (a synchronous batch); otherwise 202 with the job as it is.",
            "in": "query",
            "name": "wait",
            "schema": {
              "maximum": 60,
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "max_age": {
                    "description": "Accept cached results up to this many seconds old for every item (free cache hits), like the endpoints' max_age.",
                    "minimum": 0,
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "max_credits": {
                    "description": "Most the job may spend: a cap, never held up front (each page reserves as a synchronous request does). Default: the sum of every item's maximum price (times its max_pages). Items that would go over it are canceled.",
                    "minimum": 1,
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "metadata": {
                    "additionalProperties": {
                      "maxLength": 500,
                      "type": "string"
                    },
                    "description": "Up to 16 string pairs of your own, returned with the job and in its events.",
                    "type": "object"
                  },
                  "requests": {
                    "description": "The requests to run, 1 to 1000; custom_id must be unique within the job.",
                    "items": {
                      "properties": {
                        "custom_id": {
                          "description": "Your ID for the item (letters, digits, _ and -), echoed on its results.",
                          "maxLength": 64,
                          "minLength": 1,
                          "type": "string"
                        },
                        "endpoint": {
                          "description": "The endpoint ID: Endpoint ID on its reference page, x-socialtap-endpoint in OpenAPI (youtube.transcript; not its operationId or path).",
                          "enum": [
                            "amazon.deal_products",
                            "amazon.offers",
                            "amazon.product",
                            "amazon.reviews",
                            "amazon.search_products",
                            "amazon.seller",
                            "amazon.shop",
                            "amazon.shop_lists",
                            "amazon.shop_posts",
                            "amazon.top_products",
                            "applemusic.album",
                            "applemusic.artist",
                            "applemusic.search_albums",
                            "applemusic.search_artists",
                            "applemusic.search_playlists",
                            "applemusic.search_tracks",
                            "applemusic.top_albums",
                            "applemusic.top_playlists",
                            "applemusic.top_tracks",
                            "applemusic.track",
                            "bluesky.comments",
                            "bluesky.post",
                            "bluesky.posts",
                            "bluesky.profile",
                            "bluesky.search_posts",
                            "facebook.ad",
                            "facebook.ad_transcript",
                            "facebook.ads",
                            "facebook.comments",
                            "facebook.engagement",
                            "facebook.event",
                            "facebook.events",
                            "facebook.group",
                            "facebook.group_posts",
                            "facebook.listing",
                            "facebook.photos",
                            "facebook.place_events",
                            "facebook.post",
                            "facebook.posts",
                            "facebook.profile",
                            "facebook.reels",
                            "facebook.replies",
                            "facebook.search_ads",
                            "facebook.search_advertisers",
                            "facebook.search_events",
                            "facebook.search_groups",
                            "facebook.search_listings",
                            "facebook.search_places",
                            "facebook.search_posts",
                            "facebook.search_profiles",
                            "facebook.transcript",
                            "google.ad",
                            "google.ads",
                            "google.advertiser",
                            "google.search_ads",
                            "google.search_advertisers",
                            "google.search_suggestions",
                            "instagram.comment",
                            "instagram.comments",
                            "instagram.embed",
                            "instagram.engagement",
                            "instagram.hashtag",
                            "instagram.hashtag_posts",
                            "instagram.highlights",
                            "instagram.place",
                            "instagram.place_posts",
                            "instagram.playlist_stories",
                            "instagram.post",
                            "instagram.posts",
                            "instagram.profile",
                            "instagram.reels",
                            "instagram.search_hashtags",
                            "instagram.search_places",
                            "instagram.search_posts",
                            "instagram.search_profiles",
                            "instagram.search_sounds",
                            "instagram.search_suggestions",
                            "instagram.similar_profiles",
                            "instagram.sound",
                            "instagram.sound_posts",
                            "instagram.story",
                            "instagram.topic",
                            "instagram.transcript",
                            "instagram.trending_posts",
                            "instagram.username",
                            "kick.post",
                            "kick.transcript",
                            "komi.page",
                            "kwai.post",
                            "kwai.posts",
                            "kwai.profile",
                            "linkbio.profile",
                            "linkedin.ad",
                            "linkedin.post",
                            "linkedin.profile",
                            "linkedin.search_ads",
                            "linkedin.search_posts",
                            "linkedin.search_profiles",
                            "linkme.profile",
                            "linktree.profile",
                            "pillar.page",
                            "pinterest.board",
                            "pinterest.board_pins",
                            "pinterest.boards",
                            "pinterest.pin",
                            "pinterest.pins",
                            "pinterest.profile",
                            "pinterest.search_pins",
                            "pinterest.top_trends",
                            "pinterest.topic",
                            "pinterest.web_page",
                            "reddit.comments",
                            "reddit.engagement",
                            "reddit.post",
                            "reddit.posts",
                            "reddit.profile",
                            "reddit.profile_comments",
                            "reddit.search_comments",
                            "reddit.search_posts",
                            "reddit.search_profiles",
                            "reddit.search_subreddits",
                            "reddit.subreddit",
                            "reddit.subreddit_posts",
                            "reddit.transcript",
                            "rumble.comments",
                            "rumble.engagement",
                            "rumble.post",
                            "rumble.posts",
                            "rumble.profile",
                            "rumble.search_posts",
                            "rumble.transcript",
                            "snapchat.comments",
                            "snapchat.profile",
                            "snapchat.spotlight",
                            "soundcloud.artist",
                            "soundcloud.track",
                            "soundcloud.tracks",
                            "spotify.album",
                            "spotify.artist",
                            "spotify.playlist",
                            "spotify.playlist_tracks",
                            "spotify.podcast",
                            "spotify.podcast_episodes",
                            "spotify.search_albums",
                            "spotify.search_artists",
                            "spotify.search_playlists",
                            "spotify.search_podcasts",
                            "spotify.search_tracks",
                            "spotify.track",
                            "telegram.channel",
                            "telegram.channel_posts",
                            "telegram.post",
                            "telegram.search_channels",
                            "threads.comments",
                            "threads.post",
                            "threads.posts",
                            "threads.profile",
                            "threads.search_posts",
                            "threads.search_profiles",
                            "tiktok.ad",
                            "tiktok.comment",
                            "tiktok.comments",
                            "tiktok.download",
                            "tiktok.effect",
                            "tiktok.effect_posts",
                            "tiktok.engagement",
                            "tiktok.followers",
                            "tiktok.following",
                            "tiktok.hashtag",
                            "tiktok.hashtag_posts",
                            "tiktok.liked_posts",
                            "tiktok.live",
                            "tiktok.place_posts",
                            "tiktok.playlist_posts",
                            "tiktok.playlists",
                            "tiktok.post",
                            "tiktok.posts",
                            "tiktok.profile",
                            "tiktok.replies",
                            "tiktok.search_ads",
                            "tiktok.search_hashtags",
                            "tiktok.search_posts",
                            "tiktok.search_profiles",
                            "tiktok.search_sounds",
                            "tiktok.search_suggestions",
                            "tiktok.search_top",
                            "tiktok.sound",
                            "tiktok.sound_posts",
                            "tiktok.top_ads",
                            "tiktok.top_posts",
                            "tiktok.transcript",
                            "tiktok.trending_hashtags",
                            "tiktok.trending_posts",
                            "tiktokshop.product",
                            "tiktokshop.products",
                            "tiktokshop.reviews",
                            "tiktokshop.search_products",
                            "truthsocial.post",
                            "truthsocial.posts",
                            "truthsocial.profile",
                            "twitch.profile",
                            "twitch.schedule",
                            "twitch.transcript",
                            "twitch.video",
                            "twitch.videos",
                            "x.community",
                            "x.post",
                            "x.profile",
                            "x.search_communities",
                            "x.search_hashtags",
                            "x.search_posts",
                            "x.search_profiles",
                            "youtube.comments",
                            "youtube.engagement",
                            "youtube.post",
                            "youtube.posts",
                            "youtube.profile",
                            "youtube.transcript"
                          ],
                          "type": "string"
                        },
                        "max_pages": {
                          "description": "List endpoints only: walk up to this many pages with the cursor (default 1). Each page is a result and costs a page's price.",
                          "maximum": 1000,
                          "minimum": 1,
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "params": {
                          "additionalProperties": {},
                          "description": "The endpoint's query params, as you would send them to it (strings, numbers or booleans).",
                          "type": "object"
                        }
                      },
                      "required": [
                        "custom_id",
                        "endpoint",
                        "params"
                      ],
                      "type": "object"
                    },
                    "maxItems": 1000,
                    "minItems": 1,
                    "type": "array"
                  },
                  "webhook_url": {
                    "description": "Also deliver this job's job.* events to this URL: the URL of one of the account's webhook endpoints (its secret signs them).",
                    "maxLength": 2048,
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "requests"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "cancel_requested_at": {
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "created_at": {
                          "format": "date-time",
                          "type": "string"
                        },
                        "credits": {
                          "properties": {
                            "charged": {
                              "description": "Credits charged so far, each page once (items' prices; failed items are free).",
                              "type": "integer"
                            },
                            "max": {
                              "description": "max_credits: the most the job may spend.",
                              "type": "integer"
                            },
                            "reserved": {
                              "description": "Credits its running pages may still use (0 once the job ends).",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "max",
                            "reserved",
                            "charged"
                          ],
                          "type": "object"
                        },
                        "expires_at": {
                          "description": "The deadline: items not ended by then expire.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "finished_at": {
                          "description": "When the job ended; null while it runs.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "The job ID (job_…).",
                          "type": "string"
                        },
                        "max_age": {
                          "description": "The job's max_age; null when it accepts no cached results.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "metadata": {
                          "additionalProperties": {
                            "type": "string"
                          },
                          "description": "Your metadata; {} when none.",
                          "type": "object"
                        },
                        "object": {
                          "description": "Always job.",
                          "enum": [
                            "job"
                          ],
                          "type": "string"
                        },
                        "request_counts": {
                          "properties": {
                            "canceled": {
                              "type": "integer"
                            },
                            "expired": {
                              "type": "integer"
                            },
                            "failed": {
                              "type": "integer"
                            },
                            "queued": {
                              "description": "Not started.",
                              "type": "integer"
                            },
                            "running": {
                              "description": "Started (fetching, waiting for a retry or walking pages).",
                              "type": "integer"
                            },
                            "succeeded": {
                              "type": "integer"
                            },
                            "total": {
                              "type": "integer"
                            }
                          },
                          "required": [
                            "total",
                            "queued",
                            "running",
                            "succeeded",
                            "failed",
                            "canceled",
                            "expired"
                          ],
                          "type": "object"
                        },
                        "results_expire_at": {
                          "description": "When results are deleted; null while the job runs.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "results_url": {
                          "description": "Every result as JSON Lines (one JobResult per line), signed: works without the API key until results_url_expires_at. Null until the job ends and after results_expire_at.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "results_url_expires_at": {
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "started_at": {
                          "description": "When the first item started; null before.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "description": "queued: nothing started yet. running. canceling: canceled, running items finishing. completed: every item ended (check request_counts: there is no job-level failure). canceled. expired: the deadline passed; unfinished items expired.",
                          "enum": [
                            "queued",
                            "running",
                            "canceling",
                            "completed",
                            "canceled",
                            "expired"
                          ],
                          "type": "string"
                        },
                        "webhook_url": {
                          "description": "The job's own webhook URL; null when none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "status",
                        "request_counts",
                        "credits",
                        "max_age",
                        "metadata",
                        "webhook_url",
                        "created_at",
                        "started_at",
                        "finished_at",
                        "cancel_requested_at",
                        "expires_at",
                        "results_url",
                        "results_url_expires_at",
                        "results_expire_at"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "results": {
                      "description": "Only on 200 from create with wait: the first page of results.",
                      "items": {
                        "properties": {
                          "completed_at": {
                            "format": "date-time",
                            "type": "string"
                          },
                          "custom_id": {
                            "type": "string"
                          },
                          "endpoint": {
                            "enum": [
                              "amazon.deal_products",
                              "amazon.offers",
                              "amazon.product",
                              "amazon.reviews",
                              "amazon.search_products",
                              "amazon.seller",
                              "amazon.shop",
                              "amazon.shop_lists",
                              "amazon.shop_posts",
                              "amazon.top_products",
                              "applemusic.album",
                              "applemusic.artist",
                              "applemusic.search_albums",
                              "applemusic.search_artists",
                              "applemusic.search_playlists",
                              "applemusic.search_tracks",
                              "applemusic.top_albums",
                              "applemusic.top_playlists",
                              "applemusic.top_tracks",
                              "applemusic.track",
                              "bluesky.comments",
                              "bluesky.post",
                              "bluesky.posts",
                              "bluesky.profile",
                              "bluesky.search_posts",
                              "facebook.ad",
                              "facebook.ad_transcript",
                              "facebook.ads",
                              "facebook.comments",
                              "facebook.engagement",
                              "facebook.event",
                              "facebook.events",
                              "facebook.group",
                              "facebook.group_posts",
                              "facebook.listing",
                              "facebook.photos",
                              "facebook.place_events",
                              "facebook.post",
                              "facebook.posts",
                              "facebook.profile",
                              "facebook.reels",
                              "facebook.replies",
                              "facebook.search_ads",
                              "facebook.search_advertisers",
                              "facebook.search_events",
                              "facebook.search_groups",
                              "facebook.search_listings",
                              "facebook.search_places",
                              "facebook.search_posts",
                              "facebook.search_profiles",
                              "facebook.transcript",
                              "google.ad",
                              "google.ads",
                              "google.advertiser",
                              "google.search_ads",
                              "google.search_advertisers",
                              "google.search_suggestions",
                              "instagram.comment",
                              "instagram.comments",
                              "instagram.embed",
                              "instagram.engagement",
                              "instagram.hashtag",
                              "instagram.hashtag_posts",
                              "instagram.highlights",
                              "instagram.place",
                              "instagram.place_posts",
                              "instagram.playlist_stories",
                              "instagram.post",
                              "instagram.posts",
                              "instagram.profile",
                              "instagram.reels",
                              "instagram.search_hashtags",
                              "instagram.search_places",
                              "instagram.search_posts",
                              "instagram.search_profiles",
                              "instagram.search_sounds",
                              "instagram.search_suggestions",
                              "instagram.similar_profiles",
                              "instagram.sound",
                              "instagram.sound_posts",
                              "instagram.story",
                              "instagram.topic",
                              "instagram.transcript",
                              "instagram.trending_posts",
                              "instagram.username",
                              "kick.post",
                              "kick.transcript",
                              "komi.page",
                              "kwai.post",
                              "kwai.posts",
                              "kwai.profile",
                              "linkbio.profile",
                              "linkedin.ad",
                              "linkedin.post",
                              "linkedin.profile",
                              "linkedin.search_ads",
                              "linkedin.search_posts",
                              "linkedin.search_profiles",
                              "linkme.profile",
                              "linktree.profile",
                              "pillar.page",
                              "pinterest.board",
                              "pinterest.board_pins",
                              "pinterest.boards",
                              "pinterest.pin",
                              "pinterest.pins",
                              "pinterest.profile",
                              "pinterest.search_pins",
                              "pinterest.top_trends",
                              "pinterest.topic",
                              "pinterest.web_page",
                              "reddit.comments",
                              "reddit.engagement",
                              "reddit.post",
                              "reddit.posts",
                              "reddit.profile",
                              "reddit.profile_comments",
                              "reddit.search_comments",
                              "reddit.search_posts",
                              "reddit.search_profiles",
                              "reddit.search_subreddits",
                              "reddit.subreddit",
                              "reddit.subreddit_posts",
                              "reddit.transcript",
                              "rumble.comments",
                              "rumble.engagement",
                              "rumble.post",
                              "rumble.posts",
                              "rumble.profile",
                              "rumble.search_posts",
                              "rumble.transcript",
                              "snapchat.comments",
                              "snapchat.profile",
                              "snapchat.spotlight",
                              "soundcloud.artist",
                              "soundcloud.track",
                              "soundcloud.tracks",
                              "spotify.album",
                              "spotify.artist",
                              "spotify.playlist",
                              "spotify.playlist_tracks",
                              "spotify.podcast",
                              "spotify.podcast_episodes",
                              "spotify.search_albums",
                              "spotify.search_artists",
                              "spotify.search_playlists",
                              "spotify.search_podcasts",
                              "spotify.search_tracks",
                              "spotify.track",
                              "telegram.channel",
                              "telegram.channel_posts",
                              "telegram.post",
                              "telegram.search_channels",
                              "threads.comments",
                              "threads.post",
                              "threads.posts",
                              "threads.profile",
                              "threads.search_posts",
                              "threads.search_profiles",
                              "tiktok.ad",
                              "tiktok.comment",
                              "tiktok.comments",
                              "tiktok.download",
                              "tiktok.effect",
                              "tiktok.effect_posts",
                              "tiktok.engagement",
                              "tiktok.followers",
                              "tiktok.following",
                              "tiktok.hashtag",
                              "tiktok.hashtag_posts",
                              "tiktok.liked_posts",
                              "tiktok.live",
                              "tiktok.place_posts",
                              "tiktok.playlist_posts",
                              "tiktok.playlists",
                              "tiktok.post",
                              "tiktok.posts",
                              "tiktok.profile",
                              "tiktok.replies",
                              "tiktok.search_ads",
                              "tiktok.search_hashtags",
                              "tiktok.search_posts",
                              "tiktok.search_profiles",
                              "tiktok.search_sounds",
                              "tiktok.search_suggestions",
                              "tiktok.search_top",
                              "tiktok.sound",
                              "tiktok.sound_posts",
                              "tiktok.top_ads",
                              "tiktok.top_posts",
                              "tiktok.transcript",
                              "tiktok.trending_hashtags",
                              "tiktok.trending_posts",
                              "tiktokshop.product",
                              "tiktokshop.products",
                              "tiktokshop.reviews",
                              "tiktokshop.search_products",
                              "truthsocial.post",
                              "truthsocial.posts",
                              "truthsocial.profile",
                              "twitch.profile",
                              "twitch.schedule",
                              "twitch.transcript",
                              "twitch.video",
                              "twitch.videos",
                              "x.community",
                              "x.post",
                              "x.profile",
                              "x.search_communities",
                              "x.search_hashtags",
                              "x.search_posts",
                              "x.search_profiles",
                              "youtube.comments",
                              "youtube.engagement",
                              "youtube.post",
                              "youtube.posts",
                              "youtube.profile",
                              "youtube.transcript"
                            ],
                            "type": "string"
                          },
                          "error": {
                            "description": "Exactly the synchronous error object; null on success and for the job's own cancel or deadline.",
                            "properties": {
                              "charged": {
                                "description": "Whether the request was charged: always false, failed requests are free.",
                                "type": "boolean"
                              },
                              "code": {
                                "description": "Machine-readable error code (see the error codes list); stable.",
                                "type": "string"
                              },
                              "details": {
                                "additionalProperties": {},
                                "description": "The code's dynamic values (the error codes list documents each code's keys); {} when none.",
                                "type": "object"
                              },
                              "doc_url": {
                                "description": "URL of this code's documentation.",
                                "type": "string"
                              },
                              "message": {
                                "description": "What went wrong and how to fix it, for humans and agents; wording may change.",
                                "type": "string"
                              },
                              "param": {
                                "description": "The query parameter or header the error is about; null when it is not about one input.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "remediation": {
                                "description": "What to do about this code, one sentence.",
                                "type": "string"
                              },
                              "request_id": {
                                "description": "Unique request ID; include it when contacting support.",
                                "type": "string"
                              },
                              "retryable": {
                                "description": "True when repeating the same request later may succeed (after details.retry_after when present).",
                                "type": "boolean"
                              },
                              "status": {
                                "description": "The HTTP status of the response, repeated for clients that only see the body.",
                                "type": "integer"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "request_id",
                              "status",
                              "retryable",
                              "param",
                              "remediation",
                              "doc_url",
                              "details",
                              "charged"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "object": {
                            "description": "Always job_result.",
                            "enum": [
                              "job_result"
                            ],
                            "type": "string"
                          },
                          "page_index": {
                            "description": "0 for a single-item endpoint and a list's first page; n for the list's page n+1.",
                            "type": "integer"
                          },
                          "result": {
                            "description": "Exactly the synchronous success envelope; null unless succeeded.",
                            "properties": {
                              "data": {
                                "description": "The endpoint's data: its resource, or a list page's items."
                              },
                              "meta": {
                                "properties": {
                                  "client_request_id": {
                                    "description": "Your x-client-request-id, echoed; null when you sent none.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "credits_charged": {
                                    "description": "Credits charged for this request (0 for errors and cache hits).",
                                    "type": "integer"
                                  },
                                  "credits_remaining": {
                                    "description": "Account balance after this request (the x-credits-remaining header); for a busy account an estimate that may not yet subtract concurrent requests (about a second of usage), never below the real balance; null when SocialTap could not read it.",
                                    "type": [
                                      "integer",
                                      "null"
                                    ]
                                  },
                                  "fetched_at": {
                                    "description": "When the data was fetched from the platform, RFC 3339 UTC (older than the request for cache hits).",
                                    "format": "date-time",
                                    "type": "string"
                                  },
                                  "input": {
                                    "description": "What the request's url or handle resolved to: kind, platform ID and canonical URL, so you can confirm what was fetched; null for searches.",
                                    "properties": {
                                      "id": {
                                        "description": "Platform-native ID of the item; null when it is only known after the fetch and the request failed.",
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "kind": {
                                        "description": "What the input points to (profile, video, post, …). New values may be added; treat unknown values as other.",
                                        "type": "string"
                                      },
                                      "url": {
                                        "description": "Canonical URL of the item; null when unknown.",
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      }
                                    },
                                    "required": [
                                      "kind",
                                      "id",
                                      "url"
                                    ],
                                    "type": [
                                      "object",
                                      "null"
                                    ]
                                  },
                                  "is_cached": {
                                    "description": "True when served from the cache (free); see max_age.",
                                    "type": "boolean"
                                  },
                                  "latency_ms": {
                                    "description": "Time SocialTap spent on the request, in milliseconds.",
                                    "type": "integer"
                                  },
                                  "platform": {
                                    "description": "Platform ID of the endpoint (youtube, tiktok, …).",
                                    "type": "string"
                                  },
                                  "request_id": {
                                    "description": "Unique request ID; include it when contacting support.",
                                    "type": "string"
                                  },
                                  "source": {
                                    "description": "Which upstream strategy produced the data.",
                                    "type": "string"
                                  },
                                  "warnings": {
                                    "description": "Things to act on that did not fail the request: a deprecated endpoint, partial data, items a list's walk leaves out. [] when none.",
                                    "items": {
                                      "properties": {
                                        "code": {
                                          "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                          "type": "string"
                                        },
                                        "doc_url": {
                                          "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                          "type": "string"
                                        },
                                        "fields": {
                                          "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                          "items": {
                                            "type": "string"
                                          },
                                          "type": "array"
                                        },
                                        "message": {
                                          "description": "What to do about it.",
                                          "type": "string"
                                        }
                                      },
                                      "required": [
                                        "code",
                                        "message",
                                        "doc_url"
                                      ],
                                      "type": "object"
                                    },
                                    "type": "array"
                                  }
                                },
                                "required": [
                                  "request_id",
                                  "platform",
                                  "source",
                                  "is_cached",
                                  "credits_charged",
                                  "latency_ms",
                                  "fetched_at",
                                  "input",
                                  "credits_remaining",
                                  "client_request_id",
                                  "warnings"
                                ],
                                "type": "object"
                              },
                              "page": {
                                "description": "List endpoints only.",
                                "properties": {
                                  "end_reason": {
                                    "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                                    "enum": [
                                      "end",
                                      "platform_limit",
                                      "max_pages"
                                    ],
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "has_more": {
                                    "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                                    "type": "boolean"
                                  },
                                  "next_cursor": {
                                    "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "next_cursor_expires_at": {
                                    "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                                    "format": "date-time",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "has_more",
                                  "next_cursor",
                                  "next_cursor_expires_at",
                                  "end_reason"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "data",
                              "meta"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "status": {
                            "description": "The page's outcome; an item's status is its last result's. canceled and expired results carry no result (error says why when it is not the job's cancel or deadline).",
                            "enum": [
                              "succeeded",
                              "failed",
                              "canceled",
                              "expired"
                            ],
                            "type": "string"
                          },
                          "status_code": {
                            "description": "The HTTP status the synchronous request answered; null when it did not run.",
                            "type": [
                              "integer",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "object",
                          "custom_id",
                          "endpoint",
                          "page_index",
                          "status",
                          "status_code",
                          "result",
                          "error",
                          "completed_at"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "results_page": {
                      "description": "Only with results: the page object of results (continue on the results route).",
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": [
                        "object",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Run many requests (or one long one) as a job",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "cancel_requested_at": {
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "created_at": {
                          "format": "date-time",
                          "type": "string"
                        },
                        "credits": {
                          "properties": {
                            "charged": {
                              "description": "Credits charged so far, each page once (items' prices; failed items are free).",
                              "type": "integer"
                            },
                            "max": {
                              "description": "max_credits: the most the job may spend.",
                              "type": "integer"
                            },
                            "reserved": {
                              "description": "Credits its running pages may still use (0 once the job ends).",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "max",
                            "reserved",
                            "charged"
                          ],
                          "type": "object"
                        },
                        "expires_at": {
                          "description": "The deadline: items not ended by then expire.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "finished_at": {
                          "description": "When the job ended; null while it runs.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "The job ID (job_…).",
                          "type": "string"
                        },
                        "max_age": {
                          "description": "The job's max_age; null when it accepts no cached results.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "metadata": {
                          "additionalProperties": {
                            "type": "string"
                          },
                          "description": "Your metadata; {} when none.",
                          "type": "object"
                        },
                        "object": {
                          "description": "Always job.",
                          "enum": [
                            "job"
                          ],
                          "type": "string"
                        },
                        "request_counts": {
                          "properties": {
                            "canceled": {
                              "type": "integer"
                            },
                            "expired": {
                              "type": "integer"
                            },
                            "failed": {
                              "type": "integer"
                            },
                            "queued": {
                              "description": "Not started.",
                              "type": "integer"
                            },
                            "running": {
                              "description": "Started (fetching, waiting for a retry or walking pages).",
                              "type": "integer"
                            },
                            "succeeded": {
                              "type": "integer"
                            },
                            "total": {
                              "type": "integer"
                            }
                          },
                          "required": [
                            "total",
                            "queued",
                            "running",
                            "succeeded",
                            "failed",
                            "canceled",
                            "expired"
                          ],
                          "type": "object"
                        },
                        "results_expire_at": {
                          "description": "When results are deleted; null while the job runs.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "results_url": {
                          "description": "Every result as JSON Lines (one JobResult per line), signed: works without the API key until results_url_expires_at. Null until the job ends and after results_expire_at.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "results_url_expires_at": {
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "started_at": {
                          "description": "When the first item started; null before.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "description": "queued: nothing started yet. running. canceling: canceled, running items finishing. completed: every item ended (check request_counts: there is no job-level failure). canceled. expired: the deadline passed; unfinished items expired.",
                          "enum": [
                            "queued",
                            "running",
                            "canceling",
                            "completed",
                            "canceled",
                            "expired"
                          ],
                          "type": "string"
                        },
                        "webhook_url": {
                          "description": "The job's own webhook URL; null when none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "status",
                        "request_counts",
                        "credits",
                        "max_age",
                        "metadata",
                        "webhook_url",
                        "created_at",
                        "started_at",
                        "finished_at",
                        "cancel_requested_at",
                        "expires_at",
                        "results_url",
                        "results_url_expires_at",
                        "results_expire_at"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "results": {
                      "description": "Only on 200 from create with wait: the first page of results.",
                      "items": {
                        "properties": {
                          "completed_at": {
                            "format": "date-time",
                            "type": "string"
                          },
                          "custom_id": {
                            "type": "string"
                          },
                          "endpoint": {
                            "enum": [
                              "amazon.deal_products",
                              "amazon.offers",
                              "amazon.product",
                              "amazon.reviews",
                              "amazon.search_products",
                              "amazon.seller",
                              "amazon.shop",
                              "amazon.shop_lists",
                              "amazon.shop_posts",
                              "amazon.top_products",
                              "applemusic.album",
                              "applemusic.artist",
                              "applemusic.search_albums",
                              "applemusic.search_artists",
                              "applemusic.search_playlists",
                              "applemusic.search_tracks",
                              "applemusic.top_albums",
                              "applemusic.top_playlists",
                              "applemusic.top_tracks",
                              "applemusic.track",
                              "bluesky.comments",
                              "bluesky.post",
                              "bluesky.posts",
                              "bluesky.profile",
                              "bluesky.search_posts",
                              "facebook.ad",
                              "facebook.ad_transcript",
                              "facebook.ads",
                              "facebook.comments",
                              "facebook.engagement",
                              "facebook.event",
                              "facebook.events",
                              "facebook.group",
                              "facebook.group_posts",
                              "facebook.listing",
                              "facebook.photos",
                              "facebook.place_events",
                              "facebook.post",
                              "facebook.posts",
                              "facebook.profile",
                              "facebook.reels",
                              "facebook.replies",
                              "facebook.search_ads",
                              "facebook.search_advertisers",
                              "facebook.search_events",
                              "facebook.search_groups",
                              "facebook.search_listings",
                              "facebook.search_places",
                              "facebook.search_posts",
                              "facebook.search_profiles",
                              "facebook.transcript",
                              "google.ad",
                              "google.ads",
                              "google.advertiser",
                              "google.search_ads",
                              "google.search_advertisers",
                              "google.search_suggestions",
                              "instagram.comment",
                              "instagram.comments",
                              "instagram.embed",
                              "instagram.engagement",
                              "instagram.hashtag",
                              "instagram.hashtag_posts",
                              "instagram.highlights",
                              "instagram.place",
                              "instagram.place_posts",
                              "instagram.playlist_stories",
                              "instagram.post",
                              "instagram.posts",
                              "instagram.profile",
                              "instagram.reels",
                              "instagram.search_hashtags",
                              "instagram.search_places",
                              "instagram.search_posts",
                              "instagram.search_profiles",
                              "instagram.search_sounds",
                              "instagram.search_suggestions",
                              "instagram.similar_profiles",
                              "instagram.sound",
                              "instagram.sound_posts",
                              "instagram.story",
                              "instagram.topic",
                              "instagram.transcript",
                              "instagram.trending_posts",
                              "instagram.username",
                              "kick.post",
                              "kick.transcript",
                              "komi.page",
                              "kwai.post",
                              "kwai.posts",
                              "kwai.profile",
                              "linkbio.profile",
                              "linkedin.ad",
                              "linkedin.post",
                              "linkedin.profile",
                              "linkedin.search_ads",
                              "linkedin.search_posts",
                              "linkedin.search_profiles",
                              "linkme.profile",
                              "linktree.profile",
                              "pillar.page",
                              "pinterest.board",
                              "pinterest.board_pins",
                              "pinterest.boards",
                              "pinterest.pin",
                              "pinterest.pins",
                              "pinterest.profile",
                              "pinterest.search_pins",
                              "pinterest.top_trends",
                              "pinterest.topic",
                              "pinterest.web_page",
                              "reddit.comments",
                              "reddit.engagement",
                              "reddit.post",
                              "reddit.posts",
                              "reddit.profile",
                              "reddit.profile_comments",
                              "reddit.search_comments",
                              "reddit.search_posts",
                              "reddit.search_profiles",
                              "reddit.search_subreddits",
                              "reddit.subreddit",
                              "reddit.subreddit_posts",
                              "reddit.transcript",
                              "rumble.comments",
                              "rumble.engagement",
                              "rumble.post",
                              "rumble.posts",
                              "rumble.profile",
                              "rumble.search_posts",
                              "rumble.transcript",
                              "snapchat.comments",
                              "snapchat.profile",
                              "snapchat.spotlight",
                              "soundcloud.artist",
                              "soundcloud.track",
                              "soundcloud.tracks",
                              "spotify.album",
                              "spotify.artist",
                              "spotify.playlist",
                              "spotify.playlist_tracks",
                              "spotify.podcast",
                              "spotify.podcast_episodes",
                              "spotify.search_albums",
                              "spotify.search_artists",
                              "spotify.search_playlists",
                              "spotify.search_podcasts",
                              "spotify.search_tracks",
                              "spotify.track",
                              "telegram.channel",
                              "telegram.channel_posts",
                              "telegram.post",
                              "telegram.search_channels",
                              "threads.comments",
                              "threads.post",
                              "threads.posts",
                              "threads.profile",
                              "threads.search_posts",
                              "threads.search_profiles",
                              "tiktok.ad",
                              "tiktok.comment",
                              "tiktok.comments",
                              "tiktok.download",
                              "tiktok.effect",
                              "tiktok.effect_posts",
                              "tiktok.engagement",
                              "tiktok.followers",
                              "tiktok.following",
                              "tiktok.hashtag",
                              "tiktok.hashtag_posts",
                              "tiktok.liked_posts",
                              "tiktok.live",
                              "tiktok.place_posts",
                              "tiktok.playlist_posts",
                              "tiktok.playlists",
                              "tiktok.post",
                              "tiktok.posts",
                              "tiktok.profile",
                              "tiktok.replies",
                              "tiktok.search_ads",
                              "tiktok.search_hashtags",
                              "tiktok.search_posts",
                              "tiktok.search_profiles",
                              "tiktok.search_sounds",
                              "tiktok.search_suggestions",
                              "tiktok.search_top",
                              "tiktok.sound",
                              "tiktok.sound_posts",
                              "tiktok.top_ads",
                              "tiktok.top_posts",
                              "tiktok.transcript",
                              "tiktok.trending_hashtags",
                              "tiktok.trending_posts",
                              "tiktokshop.product",
                              "tiktokshop.products",
                              "tiktokshop.reviews",
                              "tiktokshop.search_products",
                              "truthsocial.post",
                              "truthsocial.posts",
                              "truthsocial.profile",
                              "twitch.profile",
                              "twitch.schedule",
                              "twitch.transcript",
                              "twitch.video",
                              "twitch.videos",
                              "x.community",
                              "x.post",
                              "x.profile",
                              "x.search_communities",
                              "x.search_hashtags",
                              "x.search_posts",
                              "x.search_profiles",
                              "youtube.comments",
                              "youtube.engagement",
                              "youtube.post",
                              "youtube.posts",
                              "youtube.profile",
                              "youtube.transcript"
                            ],
                            "type": "string"
                          },
                          "error": {
                            "description": "Exactly the synchronous error object; null on success and for the job's own cancel or deadline.",
                            "properties": {
                              "charged": {
                                "description": "Whether the request was charged: always false, failed requests are free.",
                                "type": "boolean"
                              },
                              "code": {
                                "description": "Machine-readable error code (see the error codes list); stable.",
                                "type": "string"
                              },
                              "details": {
                                "additionalProperties": {},
                                "description": "The code's dynamic values (the error codes list documents each code's keys); {} when none.",
                                "type": "object"
                              },
                              "doc_url": {
                                "description": "URL of this code's documentation.",
                                "type": "string"
                              },
                              "message": {
                                "description": "What went wrong and how to fix it, for humans and agents; wording may change.",
                                "type": "string"
                              },
                              "param": {
                                "description": "The query parameter or header the error is about; null when it is not about one input.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "remediation": {
                                "description": "What to do about this code, one sentence.",
                                "type": "string"
                              },
                              "request_id": {
                                "description": "Unique request ID; include it when contacting support.",
                                "type": "string"
                              },
                              "retryable": {
                                "description": "True when repeating the same request later may succeed (after details.retry_after when present).",
                                "type": "boolean"
                              },
                              "status": {
                                "description": "The HTTP status of the response, repeated for clients that only see the body.",
                                "type": "integer"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "request_id",
                              "status",
                              "retryable",
                              "param",
                              "remediation",
                              "doc_url",
                              "details",
                              "charged"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "object": {
                            "description": "Always job_result.",
                            "enum": [
                              "job_result"
                            ],
                            "type": "string"
                          },
                          "page_index": {
                            "description": "0 for a single-item endpoint and a list's first page; n for the list's page n+1.",
                            "type": "integer"
                          },
                          "result": {
                            "description": "Exactly the synchronous success envelope; null unless succeeded.",
                            "properties": {
                              "data": {
                                "description": "The endpoint's data: its resource, or a list page's items."
                              },
                              "meta": {
                                "properties": {
                                  "client_request_id": {
                                    "description": "Your x-client-request-id, echoed; null when you sent none.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "credits_charged": {
                                    "description": "Credits charged for this request (0 for errors and cache hits).",
                                    "type": "integer"
                                  },
                                  "credits_remaining": {
                                    "description": "Account balance after this request (the x-credits-remaining header); for a busy account an estimate that may not yet subtract concurrent requests (about a second of usage), never below the real balance; null when SocialTap could not read it.",
                                    "type": [
                                      "integer",
                                      "null"
                                    ]
                                  },
                                  "fetched_at": {
                                    "description": "When the data was fetched from the platform, RFC 3339 UTC (older than the request for cache hits).",
                                    "format": "date-time",
                                    "type": "string"
                                  },
                                  "input": {
                                    "description": "What the request's url or handle resolved to: kind, platform ID and canonical URL, so you can confirm what was fetched; null for searches.",
                                    "properties": {
                                      "id": {
                                        "description": "Platform-native ID of the item; null when it is only known after the fetch and the request failed.",
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "kind": {
                                        "description": "What the input points to (profile, video, post, …). New values may be added; treat unknown values as other.",
                                        "type": "string"
                                      },
                                      "url": {
                                        "description": "Canonical URL of the item; null when unknown.",
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      }
                                    },
                                    "required": [
                                      "kind",
                                      "id",
                                      "url"
                                    ],
                                    "type": [
                                      "object",
                                      "null"
                                    ]
                                  },
                                  "is_cached": {
                                    "description": "True when served from the cache (free); see max_age.",
                                    "type": "boolean"
                                  },
                                  "latency_ms": {
                                    "description": "Time SocialTap spent on the request, in milliseconds.",
                                    "type": "integer"
                                  },
                                  "platform": {
                                    "description": "Platform ID of the endpoint (youtube, tiktok, …).",
                                    "type": "string"
                                  },
                                  "request_id": {
                                    "description": "Unique request ID; include it when contacting support.",
                                    "type": "string"
                                  },
                                  "source": {
                                    "description": "Which upstream strategy produced the data.",
                                    "type": "string"
                                  },
                                  "warnings": {
                                    "description": "Things to act on that did not fail the request: a deprecated endpoint, partial data, items a list's walk leaves out. [] when none.",
                                    "items": {
                                      "properties": {
                                        "code": {
                                          "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                          "type": "string"
                                        },
                                        "doc_url": {
                                          "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                          "type": "string"
                                        },
                                        "fields": {
                                          "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                          "items": {
                                            "type": "string"
                                          },
                                          "type": "array"
                                        },
                                        "message": {
                                          "description": "What to do about it.",
                                          "type": "string"
                                        }
                                      },
                                      "required": [
                                        "code",
                                        "message",
                                        "doc_url"
                                      ],
                                      "type": "object"
                                    },
                                    "type": "array"
                                  }
                                },
                                "required": [
                                  "request_id",
                                  "platform",
                                  "source",
                                  "is_cached",
                                  "credits_charged",
                                  "latency_ms",
                                  "fetched_at",
                                  "input",
                                  "credits_remaining",
                                  "client_request_id",
                                  "warnings"
                                ],
                                "type": "object"
                              },
                              "page": {
                                "description": "List endpoints only.",
                                "properties": {
                                  "end_reason": {
                                    "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                                    "enum": [
                                      "end",
                                      "platform_limit",
                                      "max_pages"
                                    ],
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "has_more": {
                                    "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                                    "type": "boolean"
                                  },
                                  "next_cursor": {
                                    "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "next_cursor_expires_at": {
                                    "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                                    "format": "date-time",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "has_more",
                                  "next_cursor",
                                  "next_cursor_expires_at",
                                  "end_reason"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "data",
                              "meta"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "status": {
                            "description": "The page's outcome; an item's status is its last result's. canceled and expired results carry no result (error says why when it is not the job's cancel or deadline).",
                            "enum": [
                              "succeeded",
                              "failed",
                              "canceled",
                              "expired"
                            ],
                            "type": "string"
                          },
                          "status_code": {
                            "description": "The HTTP status the synchronous request answered; null when it did not run.",
                            "type": [
                              "integer",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "object",
                          "custom_id",
                          "endpoint",
                          "page_index",
                          "status",
                          "status_code",
                          "result",
                          "error",
                          "completed_at"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "results_page": {
                      "description": "Only with results: the page object of results (continue on the results route).",
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": [
                        "object",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Accepted: the job continues in the background (poll its Location, free).",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "location": {
                "$ref": "#/components/headers/location"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Run many requests (or one long one) as a job",
        "tags": [
          "Jobs"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "member",
          "scope": "jobs"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/jobs/{id}": {
      "get": {
        "description": "The job's status, per-state request counts and credits. Free: poll it, or long-poll with `wait`.\n\n**Auth:** an API key with the `jobs:read` scope, or the dashboard session.",
        "operationId": "jobs.get",
        "parameters": [
          {
            "description": "Job ID (job_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Seconds to wait for the job to end before answering (a long poll): the answer is the job as it is then.",
            "in": "query",
            "name": "wait",
            "schema": {
              "maximum": 60,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "cancel_requested_at": {
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "created_at": {
                          "format": "date-time",
                          "type": "string"
                        },
                        "credits": {
                          "properties": {
                            "charged": {
                              "description": "Credits charged so far, each page once (items' prices; failed items are free).",
                              "type": "integer"
                            },
                            "max": {
                              "description": "max_credits: the most the job may spend.",
                              "type": "integer"
                            },
                            "reserved": {
                              "description": "Credits its running pages may still use (0 once the job ends).",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "max",
                            "reserved",
                            "charged"
                          ],
                          "type": "object"
                        },
                        "expires_at": {
                          "description": "The deadline: items not ended by then expire.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "finished_at": {
                          "description": "When the job ended; null while it runs.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "The job ID (job_…).",
                          "type": "string"
                        },
                        "max_age": {
                          "description": "The job's max_age; null when it accepts no cached results.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "metadata": {
                          "additionalProperties": {
                            "type": "string"
                          },
                          "description": "Your metadata; {} when none.",
                          "type": "object"
                        },
                        "object": {
                          "description": "Always job.",
                          "enum": [
                            "job"
                          ],
                          "type": "string"
                        },
                        "request_counts": {
                          "properties": {
                            "canceled": {
                              "type": "integer"
                            },
                            "expired": {
                              "type": "integer"
                            },
                            "failed": {
                              "type": "integer"
                            },
                            "queued": {
                              "description": "Not started.",
                              "type": "integer"
                            },
                            "running": {
                              "description": "Started (fetching, waiting for a retry or walking pages).",
                              "type": "integer"
                            },
                            "succeeded": {
                              "type": "integer"
                            },
                            "total": {
                              "type": "integer"
                            }
                          },
                          "required": [
                            "total",
                            "queued",
                            "running",
                            "succeeded",
                            "failed",
                            "canceled",
                            "expired"
                          ],
                          "type": "object"
                        },
                        "results_expire_at": {
                          "description": "When results are deleted; null while the job runs.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "results_url": {
                          "description": "Every result as JSON Lines (one JobResult per line), signed: works without the API key until results_url_expires_at. Null until the job ends and after results_expire_at.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "results_url_expires_at": {
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "started_at": {
                          "description": "When the first item started; null before.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "description": "queued: nothing started yet. running. canceling: canceled, running items finishing. completed: every item ended (check request_counts: there is no job-level failure). canceled. expired: the deadline passed; unfinished items expired.",
                          "enum": [
                            "queued",
                            "running",
                            "canceling",
                            "completed",
                            "canceled",
                            "expired"
                          ],
                          "type": "string"
                        },
                        "webhook_url": {
                          "description": "The job's own webhook URL; null when none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "status",
                        "request_counts",
                        "credits",
                        "max_age",
                        "metadata",
                        "webhook_url",
                        "created_at",
                        "started_at",
                        "finished_at",
                        "cancel_requested_at",
                        "expires_at",
                        "results_url",
                        "results_url_expires_at",
                        "results_expire_at"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get a job (free to poll)",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "job_not_found": {
                    "$ref": "#/components/examples/job_not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`job_not_found`: The account has no job with this ID: the ID is wrong, or the job is past its retention. Check the job ID. Finished jobs are kept for a limited time.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Get a job (free to poll)",
        "tags": [
          "Jobs"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "member",
          "scope": "jobs:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/jobs/{id}/cancel": {
      "post": {
        "description": "Stops the job: items not started become `canceled` (free); items already running finish and are charged. The job is `canceling` until they do, then `canceled`. Canceling an ended job changes nothing. Free.\n\n**Auth:** an API key with the `jobs` scope, or the dashboard session.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "jobs.cancel",
        "parameters": [
          {
            "description": "Job ID (job_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "cancel_requested_at": {
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "created_at": {
                          "format": "date-time",
                          "type": "string"
                        },
                        "credits": {
                          "properties": {
                            "charged": {
                              "description": "Credits charged so far, each page once (items' prices; failed items are free).",
                              "type": "integer"
                            },
                            "max": {
                              "description": "max_credits: the most the job may spend.",
                              "type": "integer"
                            },
                            "reserved": {
                              "description": "Credits its running pages may still use (0 once the job ends).",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "max",
                            "reserved",
                            "charged"
                          ],
                          "type": "object"
                        },
                        "expires_at": {
                          "description": "The deadline: items not ended by then expire.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "finished_at": {
                          "description": "When the job ended; null while it runs.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "id": {
                          "description": "The job ID (job_…).",
                          "type": "string"
                        },
                        "max_age": {
                          "description": "The job's max_age; null when it accepts no cached results.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "metadata": {
                          "additionalProperties": {
                            "type": "string"
                          },
                          "description": "Your metadata; {} when none.",
                          "type": "object"
                        },
                        "object": {
                          "description": "Always job.",
                          "enum": [
                            "job"
                          ],
                          "type": "string"
                        },
                        "request_counts": {
                          "properties": {
                            "canceled": {
                              "type": "integer"
                            },
                            "expired": {
                              "type": "integer"
                            },
                            "failed": {
                              "type": "integer"
                            },
                            "queued": {
                              "description": "Not started.",
                              "type": "integer"
                            },
                            "running": {
                              "description": "Started (fetching, waiting for a retry or walking pages).",
                              "type": "integer"
                            },
                            "succeeded": {
                              "type": "integer"
                            },
                            "total": {
                              "type": "integer"
                            }
                          },
                          "required": [
                            "total",
                            "queued",
                            "running",
                            "succeeded",
                            "failed",
                            "canceled",
                            "expired"
                          ],
                          "type": "object"
                        },
                        "results_expire_at": {
                          "description": "When results are deleted; null while the job runs.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "results_url": {
                          "description": "Every result as JSON Lines (one JobResult per line), signed: works without the API key until results_url_expires_at. Null until the job ends and after results_expire_at.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "results_url_expires_at": {
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "started_at": {
                          "description": "When the first item started; null before.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "description": "queued: nothing started yet. running. canceling: canceled, running items finishing. completed: every item ended (check request_counts: there is no job-level failure). canceled. expired: the deadline passed; unfinished items expired.",
                          "enum": [
                            "queued",
                            "running",
                            "canceling",
                            "completed",
                            "canceled",
                            "expired"
                          ],
                          "type": "string"
                        },
                        "webhook_url": {
                          "description": "The job's own webhook URL; null when none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "status",
                        "request_counts",
                        "credits",
                        "max_age",
                        "metadata",
                        "webhook_url",
                        "created_at",
                        "started_at",
                        "finished_at",
                        "cancel_requested_at",
                        "expires_at",
                        "results_url",
                        "results_url_expires_at",
                        "results_expire_at"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Cancel a job",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "job_not_found": {
                    "$ref": "#/components/examples/job_not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`job_not_found`: The account has no job with this ID: the ID is wrong, or the job is past its retention. Check the job ID. Finished jobs are kept for a limited time.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Cancel a job",
        "tags": [
          "Jobs"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "jobs"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/jobs/{id}/results": {
      "get": {
        "description": "The job's results in the order they completed, cursor-paged: one per page an item fetched (a single-item endpoint has one page), and one with the item's final status when it ended without a result (canceled, expired). `result` is exactly the synchronous response's envelope, `error` exactly its error object. Results of a running job can be read as they arrive: keep the last `page.next_cursor` and continue from it. Kept `results_retention_s` (7 days) after the job ends. Free.\n\n**Auth:** an API key with the `jobs:read` scope, or the dashboard session.",
        "operationId": "jobs.results.list",
        "parameters": [
          {
            "description": "Job ID (job_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Only results in this status (e.g. failed, to resubmit them).",
            "in": "query",
            "name": "status",
            "schema": {
              "enum": [
                "succeeded",
                "failed",
                "canceled",
                "expired"
              ],
              "type": "string"
            }
          },
          {
            "description": "Results per page (default and maximum 100).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page; omit to start from the first result.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "completed_at": {
                            "format": "date-time",
                            "type": "string"
                          },
                          "custom_id": {
                            "type": "string"
                          },
                          "endpoint": {
                            "enum": [
                              "amazon.deal_products",
                              "amazon.offers",
                              "amazon.product",
                              "amazon.reviews",
                              "amazon.search_products",
                              "amazon.seller",
                              "amazon.shop",
                              "amazon.shop_lists",
                              "amazon.shop_posts",
                              "amazon.top_products",
                              "applemusic.album",
                              "applemusic.artist",
                              "applemusic.search_albums",
                              "applemusic.search_artists",
                              "applemusic.search_playlists",
                              "applemusic.search_tracks",
                              "applemusic.top_albums",
                              "applemusic.top_playlists",
                              "applemusic.top_tracks",
                              "applemusic.track",
                              "bluesky.comments",
                              "bluesky.post",
                              "bluesky.posts",
                              "bluesky.profile",
                              "bluesky.search_posts",
                              "facebook.ad",
                              "facebook.ad_transcript",
                              "facebook.ads",
                              "facebook.comments",
                              "facebook.engagement",
                              "facebook.event",
                              "facebook.events",
                              "facebook.group",
                              "facebook.group_posts",
                              "facebook.listing",
                              "facebook.photos",
                              "facebook.place_events",
                              "facebook.post",
                              "facebook.posts",
                              "facebook.profile",
                              "facebook.reels",
                              "facebook.replies",
                              "facebook.search_ads",
                              "facebook.search_advertisers",
                              "facebook.search_events",
                              "facebook.search_groups",
                              "facebook.search_listings",
                              "facebook.search_places",
                              "facebook.search_posts",
                              "facebook.search_profiles",
                              "facebook.transcript",
                              "google.ad",
                              "google.ads",
                              "google.advertiser",
                              "google.search_ads",
                              "google.search_advertisers",
                              "google.search_suggestions",
                              "instagram.comment",
                              "instagram.comments",
                              "instagram.embed",
                              "instagram.engagement",
                              "instagram.hashtag",
                              "instagram.hashtag_posts",
                              "instagram.highlights",
                              "instagram.place",
                              "instagram.place_posts",
                              "instagram.playlist_stories",
                              "instagram.post",
                              "instagram.posts",
                              "instagram.profile",
                              "instagram.reels",
                              "instagram.search_hashtags",
                              "instagram.search_places",
                              "instagram.search_posts",
                              "instagram.search_profiles",
                              "instagram.search_sounds",
                              "instagram.search_suggestions",
                              "instagram.similar_profiles",
                              "instagram.sound",
                              "instagram.sound_posts",
                              "instagram.story",
                              "instagram.topic",
                              "instagram.transcript",
                              "instagram.trending_posts",
                              "instagram.username",
                              "kick.post",
                              "kick.transcript",
                              "komi.page",
                              "kwai.post",
                              "kwai.posts",
                              "kwai.profile",
                              "linkbio.profile",
                              "linkedin.ad",
                              "linkedin.post",
                              "linkedin.profile",
                              "linkedin.search_ads",
                              "linkedin.search_posts",
                              "linkedin.search_profiles",
                              "linkme.profile",
                              "linktree.profile",
                              "pillar.page",
                              "pinterest.board",
                              "pinterest.board_pins",
                              "pinterest.boards",
                              "pinterest.pin",
                              "pinterest.pins",
                              "pinterest.profile",
                              "pinterest.search_pins",
                              "pinterest.top_trends",
                              "pinterest.topic",
                              "pinterest.web_page",
                              "reddit.comments",
                              "reddit.engagement",
                              "reddit.post",
                              "reddit.posts",
                              "reddit.profile",
                              "reddit.profile_comments",
                              "reddit.search_comments",
                              "reddit.search_posts",
                              "reddit.search_profiles",
                              "reddit.search_subreddits",
                              "reddit.subreddit",
                              "reddit.subreddit_posts",
                              "reddit.transcript",
                              "rumble.comments",
                              "rumble.engagement",
                              "rumble.post",
                              "rumble.posts",
                              "rumble.profile",
                              "rumble.search_posts",
                              "rumble.transcript",
                              "snapchat.comments",
                              "snapchat.profile",
                              "snapchat.spotlight",
                              "soundcloud.artist",
                              "soundcloud.track",
                              "soundcloud.tracks",
                              "spotify.album",
                              "spotify.artist",
                              "spotify.playlist",
                              "spotify.playlist_tracks",
                              "spotify.podcast",
                              "spotify.podcast_episodes",
                              "spotify.search_albums",
                              "spotify.search_artists",
                              "spotify.search_playlists",
                              "spotify.search_podcasts",
                              "spotify.search_tracks",
                              "spotify.track",
                              "telegram.channel",
                              "telegram.channel_posts",
                              "telegram.post",
                              "telegram.search_channels",
                              "threads.comments",
                              "threads.post",
                              "threads.posts",
                              "threads.profile",
                              "threads.search_posts",
                              "threads.search_profiles",
                              "tiktok.ad",
                              "tiktok.comment",
                              "tiktok.comments",
                              "tiktok.download",
                              "tiktok.effect",
                              "tiktok.effect_posts",
                              "tiktok.engagement",
                              "tiktok.followers",
                              "tiktok.following",
                              "tiktok.hashtag",
                              "tiktok.hashtag_posts",
                              "tiktok.liked_posts",
                              "tiktok.live",
                              "tiktok.place_posts",
                              "tiktok.playlist_posts",
                              "tiktok.playlists",
                              "tiktok.post",
                              "tiktok.posts",
                              "tiktok.profile",
                              "tiktok.replies",
                              "tiktok.search_ads",
                              "tiktok.search_hashtags",
                              "tiktok.search_posts",
                              "tiktok.search_profiles",
                              "tiktok.search_sounds",
                              "tiktok.search_suggestions",
                              "tiktok.search_top",
                              "tiktok.sound",
                              "tiktok.sound_posts",
                              "tiktok.top_ads",
                              "tiktok.top_posts",
                              "tiktok.transcript",
                              "tiktok.trending_hashtags",
                              "tiktok.trending_posts",
                              "tiktokshop.product",
                              "tiktokshop.products",
                              "tiktokshop.reviews",
                              "tiktokshop.search_products",
                              "truthsocial.post",
                              "truthsocial.posts",
                              "truthsocial.profile",
                              "twitch.profile",
                              "twitch.schedule",
                              "twitch.transcript",
                              "twitch.video",
                              "twitch.videos",
                              "x.community",
                              "x.post",
                              "x.profile",
                              "x.search_communities",
                              "x.search_hashtags",
                              "x.search_posts",
                              "x.search_profiles",
                              "youtube.comments",
                              "youtube.engagement",
                              "youtube.post",
                              "youtube.posts",
                              "youtube.profile",
                              "youtube.transcript"
                            ],
                            "type": "string"
                          },
                          "error": {
                            "description": "Exactly the synchronous error object; null on success and for the job's own cancel or deadline.",
                            "properties": {
                              "charged": {
                                "description": "Whether the request was charged: always false, failed requests are free.",
                                "type": "boolean"
                              },
                              "code": {
                                "description": "Machine-readable error code (see the error codes list); stable.",
                                "type": "string"
                              },
                              "details": {
                                "additionalProperties": {},
                                "description": "The code's dynamic values (the error codes list documents each code's keys); {} when none.",
                                "type": "object"
                              },
                              "doc_url": {
                                "description": "URL of this code's documentation.",
                                "type": "string"
                              },
                              "message": {
                                "description": "What went wrong and how to fix it, for humans and agents; wording may change.",
                                "type": "string"
                              },
                              "param": {
                                "description": "The query parameter or header the error is about; null when it is not about one input.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "remediation": {
                                "description": "What to do about this code, one sentence.",
                                "type": "string"
                              },
                              "request_id": {
                                "description": "Unique request ID; include it when contacting support.",
                                "type": "string"
                              },
                              "retryable": {
                                "description": "True when repeating the same request later may succeed (after details.retry_after when present).",
                                "type": "boolean"
                              },
                              "status": {
                                "description": "The HTTP status of the response, repeated for clients that only see the body.",
                                "type": "integer"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "request_id",
                              "status",
                              "retryable",
                              "param",
                              "remediation",
                              "doc_url",
                              "details",
                              "charged"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "object": {
                            "description": "Always job_result.",
                            "enum": [
                              "job_result"
                            ],
                            "type": "string"
                          },
                          "page_index": {
                            "description": "0 for a single-item endpoint and a list's first page; n for the list's page n+1.",
                            "type": "integer"
                          },
                          "result": {
                            "description": "Exactly the synchronous success envelope; null unless succeeded.",
                            "properties": {
                              "data": {
                                "description": "The endpoint's data: its resource, or a list page's items."
                              },
                              "meta": {
                                "properties": {
                                  "client_request_id": {
                                    "description": "Your x-client-request-id, echoed; null when you sent none.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "credits_charged": {
                                    "description": "Credits charged for this request (0 for errors and cache hits).",
                                    "type": "integer"
                                  },
                                  "credits_remaining": {
                                    "description": "Account balance after this request (the x-credits-remaining header); for a busy account an estimate that may not yet subtract concurrent requests (about a second of usage), never below the real balance; null when SocialTap could not read it.",
                                    "type": [
                                      "integer",
                                      "null"
                                    ]
                                  },
                                  "fetched_at": {
                                    "description": "When the data was fetched from the platform, RFC 3339 UTC (older than the request for cache hits).",
                                    "format": "date-time",
                                    "type": "string"
                                  },
                                  "input": {
                                    "description": "What the request's url or handle resolved to: kind, platform ID and canonical URL, so you can confirm what was fetched; null for searches.",
                                    "properties": {
                                      "id": {
                                        "description": "Platform-native ID of the item; null when it is only known after the fetch and the request failed.",
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "kind": {
                                        "description": "What the input points to (profile, video, post, …). New values may be added; treat unknown values as other.",
                                        "type": "string"
                                      },
                                      "url": {
                                        "description": "Canonical URL of the item; null when unknown.",
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      }
                                    },
                                    "required": [
                                      "kind",
                                      "id",
                                      "url"
                                    ],
                                    "type": [
                                      "object",
                                      "null"
                                    ]
                                  },
                                  "is_cached": {
                                    "description": "True when served from the cache (free); see max_age.",
                                    "type": "boolean"
                                  },
                                  "latency_ms": {
                                    "description": "Time SocialTap spent on the request, in milliseconds.",
                                    "type": "integer"
                                  },
                                  "platform": {
                                    "description": "Platform ID of the endpoint (youtube, tiktok, …).",
                                    "type": "string"
                                  },
                                  "request_id": {
                                    "description": "Unique request ID; include it when contacting support.",
                                    "type": "string"
                                  },
                                  "source": {
                                    "description": "Which upstream strategy produced the data.",
                                    "type": "string"
                                  },
                                  "warnings": {
                                    "description": "Things to act on that did not fail the request: a deprecated endpoint, partial data, items a list's walk leaves out. [] when none.",
                                    "items": {
                                      "properties": {
                                        "code": {
                                          "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                          "type": "string"
                                        },
                                        "doc_url": {
                                          "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                          "type": "string"
                                        },
                                        "fields": {
                                          "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                          "items": {
                                            "type": "string"
                                          },
                                          "type": "array"
                                        },
                                        "message": {
                                          "description": "What to do about it.",
                                          "type": "string"
                                        }
                                      },
                                      "required": [
                                        "code",
                                        "message",
                                        "doc_url"
                                      ],
                                      "type": "object"
                                    },
                                    "type": "array"
                                  }
                                },
                                "required": [
                                  "request_id",
                                  "platform",
                                  "source",
                                  "is_cached",
                                  "credits_charged",
                                  "latency_ms",
                                  "fetched_at",
                                  "input",
                                  "credits_remaining",
                                  "client_request_id",
                                  "warnings"
                                ],
                                "type": "object"
                              },
                              "page": {
                                "description": "List endpoints only.",
                                "properties": {
                                  "end_reason": {
                                    "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                                    "enum": [
                                      "end",
                                      "platform_limit",
                                      "max_pages"
                                    ],
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "has_more": {
                                    "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                                    "type": "boolean"
                                  },
                                  "next_cursor": {
                                    "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "next_cursor_expires_at": {
                                    "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                                    "format": "date-time",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "has_more",
                                  "next_cursor",
                                  "next_cursor_expires_at",
                                  "end_reason"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "data",
                              "meta"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "status": {
                            "description": "The page's outcome; an item's status is its last result's. canceled and expired results carry no result (error says why when it is not the job's cancel or deadline).",
                            "enum": [
                              "succeeded",
                              "failed",
                              "canceled",
                              "expired"
                            ],
                            "type": "string"
                          },
                          "status_code": {
                            "description": "The HTTP status the synchronous request answered; null when it did not run.",
                            "type": [
                              "integer",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "object",
                          "custom_id",
                          "endpoint",
                          "page_index",
                          "status",
                          "status_code",
                          "result",
                          "error",
                          "completed_at"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List a job's results as they complete",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "job_not_found": {
                    "$ref": "#/components/examples/job_not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`job_not_found`: The account has no job with this ID: the ID is wrong, or the job is past its retention. Check the job ID. Finished jobs are kept for a limited time.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "List a job's results as they complete",
        "tags": [
          "Jobs"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "member",
          "scope": "jobs:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/jobs/{id}/results.jsonl": {
      "get": {
        "description": "The job's `results_url`: every result as JSON Lines (one JobResult object per line, in completion order), streamed. The URL is signed: it needs no API key and works until `results_url_expires_at`; GET the job again for a fresh one. Free.\n\n**Auth:** none: the signed URL is the credential.",
        "operationId": "jobs.results.download",
        "parameters": [
          {
            "description": "Job ID (job_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Set by SocialTap: the job's account (and mode).",
            "in": "query",
            "name": "account",
            "schema": {
              "maxLength": 100,
              "type": "string"
            }
          },
          {
            "description": "Set by SocialTap: when the URL stops working (Unix seconds).",
            "in": "query",
            "name": "expires",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Set by SocialTap: the URL's signature.",
            "in": "query",
            "name": "signature",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/jsonl": {
                "schema": {
                  "description": "One JSON object per line, each a JobResult:\n\n",
                  "type": "string"
                }
              }
            },
            "description": "Download every result of a job (JSON Lines)",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "job_not_found": {
                    "$ref": "#/components/examples/job_not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`job_not_found`: The account has no job with this ID: the ID is wrong, or the job is past its retention. Check the job ID. Finished jobs are kept for a limited time.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [],
        "summary": "Download every result of a job (JSON Lines)",
        "tags": [
          "Jobs"
        ],
        "x-socialtap-auth": {
          "auth": "none",
          "role": "",
          "scope": ""
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [],
          "retry_after_header": "retry-after",
          "retryable_codes": []
        }
      }
    },
    "/v1/kick/post": {
      "get": {
        "description": "Returns a public Kick clip from any of its links or its ID, with its title, channel, exact views, length and playback link. It also has the canonical link, thumbnail, the channel's verified badge, the category and its parent, the mature flag, when the clip was made and the moment of the stream it starts at, the broadcast's ID, the saved video it was cut from with the offset into it while Kick keeps that video, and the account that made it.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/kick/post/ (Markdown: https://socialtap.dev/docs/reference/kick/post/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/kick/post/index.md)",
          "url": "https://socialtap.dev/docs/reference/kick/post/"
        },
        "operationId": "kick.post.get",
        "parameters": [
          {
            "description": "The clip: its link (kick.com/xqc/clips/clip_01JGJHB6CEVFCQRYTVPM8DW892), the older kick.com/xqc?clip=<id>, a clips page with ?clip=<id>, its file on clips.kick.com, or its ID (clip_01JGJHB6CEVFCQRYTVPM8DW892).",
            "example": "https://kick.com/xqc/clips/clip_01JGJHB6CEVFCQRYTVPM8DW892",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The clip: its link (kick.com/xqc/clips/clip_01JGJHB6CEVFCQRYTVPM8DW892), the older kick.com/xqc?clip=<id>, a clips page with ?clip=<id>, its file on clips.kick.com, or its ID (clip_01JGJHB6CEVFCQRYTVPM8DW892).",
              "examples": [
                "https://kick.com/xqc/clips/clip_01JGJHB6CEVFCQRYTVPM8DW892"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://files.kick.com/images/user/676/profile_image/conversion/931b4e8f-5445-427c-bd82-b473530390cc-medium.webp",
                          "display_name": "xQc",
                          "id": "668",
                          "is_verified": true,
                          "url": "https://kick.com/xqc",
                          "username": "xqc"
                        },
                        "coauthors": [],
                        "duration_ms": 50000,
                        "hashtags": [],
                        "id": "clip_01JGJHB6CEVFCQRYTVPM8DW892",
                        "is_nsfw": false,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": null,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": 50000,
                            "expires_at": null,
                            "height": null,
                            "thumbnail_url": "https://clips.kick.com/clips/7a/clip_01JGJHB6CEVFCQRYTVPM8DW892/thumbnail.webp",
                            "type": "video",
                            "url": "https://clips.kick.com/clips/7a/clip_01JGJHB6CEVFCQRYTVPM8DW892/playlist.m3u8",
                            "width": null
                          }
                        ],
                        "mentions": [],
                        "metrics": {
                          "comment_count": null,
                          "like_count": null,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": null,
                          "share_count": null,
                          "view_count": 12581
                        },
                        "platform": "kick",
                        "platform_specific": {
                          "kick": {
                            "category": {
                              "banner_url": "https://files.kick.com/images/subcategories/15/banner/5546d68b-e9f9-49f9-a658-9d2ece637064",
                              "id": "15",
                              "name": "Just Chatting",
                              "parent_slug": "irl",
                              "slug": "just-chatting"
                            },
                            "clipped_by": {
                              "avatar_url": null,
                              "display_name": "cskorm",
                              "id": null,
                              "is_verified": null,
                              "url": "https://kick.com/cskorm",
                              "username": "cskorm"
                            },
                            "clipped_by_user_id": "13035177",
                            "livestream_id": "45013036",
                            "started_at": "2025-01-02T03:34:52Z",
                            "vod": null
                          }
                        },
                        "platform_type": "clip",
                        "published_at": "2025-01-02T03:37:13Z",
                        "text": null,
                        "thumbnail_url": "https://clips.kick.com/clips/7a/clip_01JGJHB6CEVFCQRYTVPM8DW892/thumbnail.webp",
                        "title": "MonkaW",
                        "type": "video",
                        "unknown_fields": [],
                        "url": "https://kick.com/xqc/clips/clip_01JGJHB6CEVFCQRYTVPM8DW892"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "kick",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 365,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "clip_01JGJHB6CEVFCQRYTVPM8DW892",
                          "url": "https://kick.com/xqc/clips/clip_01JGJHB6CEVFCQRYTVPM8DW892"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/KickPostResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact views, channel and playback link",
        "tags": [
          "Kick"
        ],
        "x-socialtap-endpoint": "kick.post",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/kick/transcript": {
      "get": {
        "description": "Returns the timed transcript of a public Kick clip from any of its links or its ID, transcribed from the clip's audio. Each segment has its start and end time, with the full text, the language heard and the clip's length. Kick has no captions to read, so every transcript comes from speech-to-text, on HLS clips and the older MP4 clips alike.\n\nReturns `{data, meta}`: `data` is a `Transcript` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 2 credits + 2 per started minute of media per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/kick/transcript/ (Markdown: https://socialtap.dev/docs/reference/kick/transcript/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/kick/transcript/index.md)",
          "url": "https://socialtap.dev/docs/reference/kick/transcript/"
        },
        "operationId": "kick.transcript.get",
        "parameters": [
          {
            "description": "The clip: its link (kick.com/xqc/clips/clip_01JGJHB6CEVFCQRYTVPM8DW892), the older kick.com/xqc?clip=<id>, a clips page with ?clip=<id>, its file on clips.kick.com, or its ID (clip_01JGJHB6CEVFCQRYTVPM8DW892).",
            "example": "https://kick.com/rdjavi/clips/clip_01J3EW5QM919XZAQMSTAK1JEK2",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The clip: its link (kick.com/xqc/clips/clip_01JGJHB6CEVFCQRYTVPM8DW892), the older kick.com/xqc?clip=<id>, a clips page with ?clip=<id>, its file on clips.kick.com, or its ID (clip_01JGJHB6CEVFCQRYTVPM8DW892).",
              "examples": [
                "https://kick.com/xqc/clips/clip_01JGJHB6CEVFCQRYTVPM8DW892"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). A hint to speech-to-text: the language the clip is spoken in. Without it the language is detected; language says which was used. It does not translate.",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). A hint to speech-to-text: the language the clip is spoken in. Without it the language is detected; language says which was used. It does not translate.",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "available_languages": [],
                        "duration_ms": 15000,
                        "id": "clip_01J3EW5QM919XZAQMSTAK1JEK2",
                        "is_auto_generated": true,
                        "language": "es",
                        "platform": "kick",
                        "platform_specific": {},
                        "segments": [
                          {
                            "end_ms": 960,
                            "start_ms": 0,
                            "text": "¿Qué es esta vaina que está sonando?"
                          },
                          {
                            "end_ms": 4000,
                            "start_ms": 2120,
                            "text": "¿Y esa música que pusieron ahí?"
                          },
                          {
                            "end_ms": 6880,
                            "start_ms": 4360,
                            "text": "No se bajen, no se bajen, no se bajen."
                          }
                        ],
                        "source": "asr",
                        "text": "¿Qué es esta vaina que está sonando? ¿Y esa música que pusieron ahí? No se bajen, no se bajen, no se bajen. ¿Pero cómo no nos vamos a bajar? ¡Las demás! ¡Dios! ¡Dios mío, qué respiración!",
                        "url": "https://kick.com/rdjavi/clips/clip_01J3EW5QM919XZAQMSTAK1JEK2"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "kick",
                        "source": "asr",
                        "is_cached": false,
                        "credits_charged": 4,
                        "latency_ms": 3617,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "clip_01J3EW5QM919XZAQMSTAK1JEK2",
                          "url": "https://kick.com/rdjavi/clips/clip_01J3EW5QM919XZAQMSTAK1JEK2"
                        },
                        "credits_remaining": 9996,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/KickTranscriptResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "no_transcript": {
                    "$ref": "#/components/examples/no_transcript"
                  },
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.\n\n`no_transcript`: The video or audio exists but has no transcript: no caption track and no speech to transcribe. Do not retry. If the platform offers other languages, try one with lang.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Timed transcript of a clip, from its audio",
        "tags": [
          "Kick"
        ],
        "x-socialtap-endpoint": "kick.transcript",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 122,
          "min_credits": 2,
          "prices": [
            {
              "credits": 2,
              "label": "2 credits + 2 per started minute of media",
              "max": 122,
              "per": 2,
              "source": "asr",
              "unit": "media_minute",
              "unit_max": 60
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "transcript",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/komi/page": {
      "get": {
        "description": "Returns a public Komi creator page with everything it shows: links, products with prices, discount codes, videos, music, podcasts and events. Music releases and podcast episodes come with their link on each streaming service, and events with their date, venue and ticket link. The page also has its ID, username, display name, bio, avatar, owner's name and its row of social and contact links. Send its link, its host or its username.\n\nReturns `{data, meta}`: `data` is a `Profile` object (Komi calls it a page) (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/komi/page/ (Markdown: https://socialtap.dev/docs/reference/komi/page/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/komi/page/index.md)",
          "url": "https://socialtap.dev/docs/reference/komi/page/"
        },
        "operationId": "komi.page.get",
        "parameters": [
          {
            "description": "The Komi page: its link (https://kimkardashian.komi.io, on any path), the host alone (kimkardashian.komi.io), or its username with or without the @.",
            "example": "https://hek.komi.io",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Komi page: its link (https://kimkardashian.komi.io, on any path), the host alone (kimkardashian.komi.io), or its username with or without the @.",
              "examples": [
                "kimkardashian"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://komi-production-assets.s3-accelerate.amazonaws.com/photos/lDMv-wPUiMipP8yyiam66.jpg?tr=w-782%2Ch-983%2Ccm-extract%2Cx-149%2Cy-45&crp=%7B%22width%22%3A782%2C%22height%22%3A983%2C%22x%22%3A149%2C%22y%22%3A45%7D",
                        "banner_url": null,
                        "bio": null,
                        "category": "Music",
                        "country_code": null,
                        "created_at": "2024-10-21T14:41:23Z",
                        "display_name": "HEKKET",
                        "external_links": [
                          {
                            "title": null,
                            "url": "https://instagram.com/hekket17603/profilecard/?igsh=MW1oNWRiODA5dWZuMg=="
                          },
                          {
                            "title": null,
                            "url": "https://youtube.com/@hekket?si=-xnVB7PdutNtbgmk"
                          },
                          {
                            "title": "DEAD BXTCH FT N8F",
                            "url": "https://on.soundcloud.com/hEQzK"
                          }
                        ],
                        "id": "fea18cd6-5ba9-4f7d-94ea-3d08c7cf31d7",
                        "is_private": false,
                        "is_verified": null,
                        "location": null,
                        "metrics": {
                          "follower_count": null,
                          "following_count": null,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "komi",
                        "platform_specific": {
                          "komi": {
                            "display_name_image_url": null,
                            "first_name": "HEKKET",
                            "items": [
                              {
                                "coupon_code": null,
                                "currency": null,
                                "description": null,
                                "group": null,
                                "id": "ebefa060-2c52-4119-97a4-94f084bce23c",
                                "is_sold_out": null,
                                "links": [],
                                "location": null,
                                "price": null,
                                "section": "SoundCloud",
                                "starts_at": null,
                                "thumbnail_url": "https://komi-production-assets.s3-accelerate.amazonaws.com/photos/4QeDwoRB1cv8sG2g47Jde.jpg",
                                "title": "DEAD BXTCH FT N8F",
                                "type": "link",
                                "url": "https://on.soundcloud.com/hEQzK",
                                "venue": null
                              },
                              {
                                "coupon_code": null,
                                "currency": null,
                                "description": null,
                                "group": null,
                                "id": "92612586-9372-4ee0-9662-caffa7fccd3e",
                                "is_sold_out": null,
                                "links": [],
                                "location": null,
                                "price": null,
                                "section": "YouTube Videos",
                                "starts_at": null,
                                "thumbnail_url": "https://i.ytimg.com/vi/aRR9J4af9gY/hqdefault.jpg",
                                "title": "HEKKET & OMYSLIM - STRESSIN OUT",
                                "type": "youtube_video",
                                "url": "https://youtu.be/aRR9J4af9gY?si=vATDxe2tEjbf3gMP",
                                "venue": null
                              },
                              {
                                "coupon_code": null,
                                "currency": null,
                                "description": null,
                                "group": null,
                                "id": "342924db-5b88-488c-8a9f-26e593af8cf2",
                                "is_sold_out": null,
                                "links": [],
                                "location": null,
                                "price": null,
                                "section": "YouTube Videos",
                                "starts_at": null,
                                "thumbnail_url": "https://i.ytimg.com/vi/SFzYp5P0U6k/hqdefault.jpg",
                                "title": "HEKKET - DEAD BXTCH (feat N8F & Prod By DELIXE)",
                                "type": "youtube_video",
                                "url": "https://youtu.be/SFzYp5P0U6k?si=qNgExztHYFqS06Iw",
                                "venue": null
                              }
                            ],
                            "last_name": null,
                            "social_links": [
                              {
                                "type": "instagram",
                                "url": "https://instagram.com/hekket17603/profilecard/?igsh=MW1oNWRiODA5dWZuMg=="
                              },
                              {
                                "type": "youtube",
                                "url": "https://youtube.com/@hekket?si=-xnVB7PdutNtbgmk"
                              }
                            ]
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://hek.komi.io",
                        "username": "hek"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "komi",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 2377,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "fea18cd6-5ba9-4f7d-94ea-3d08c7cf31d7",
                          "url": "https://hek.komi.io"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/KomiPageResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Products, discount codes, music, events and links",
        "tags": [
          "Komi"
        ],
        "x-socialtap-endpoint": "komi.page",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/kwai/post": {
      "get": {
        "description": "Returns a public Kwai short video from its link, share link or post ID, with exact views, likes, comments and shares and its video file. It also has the caption, hashtags, mentions and tagged accounts, the exact publish time and length, the cover, the author with their verified badge, the sound with its audio file, the tagged place, Kwai's topic, its AI label, and the source of a duet.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/kwai/post/ (Markdown: https://socialtap.dev/docs/reference/kwai/post/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/kwai/post/index.md)",
          "url": "https://socialtap.dev/docs/reference/kwai/post/"
        },
        "operationId": "kwai.post.get",
        "parameters": [
          {
            "description": "The Kwai post: a link (kwai.com/@KwaiBrasilOficial/video/5217007328706437238, /video/<id>, /embed/<id>, /search/<words>/video/<id>, /@<name>/photo/<id>, m.kwai.com/photo/<user>/<id>, snackvideo.com), a share link (k.kwai.com/p/<code>, s.kw.ai, kw.ai, kwai-video.com, s.kwai.app/s/<code>) or a bare post ID.",
            "example": "https://www.kwai.com/@KwaiBrasilOficial/video/5217007328706437238",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The Kwai post: a link (kwai.com/@KwaiBrasilOficial/video/5217007328706437238, /video/<id>, /embed/<id>, /search/<words>/video/<id>, /@<name>/photo/<id>, m.kwai.com/photo/<user>/<id>, snackvideo.com), a share link (k.kwai.com/p/<code>, s.kw.ai, kw.ai, kwai-video.com, s.kwai.app/s/<code>) or a bare post ID.",
              "examples": [
                "https://www.kwai.com/@KwaiBrasilOficial/video/5217007328706437238"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://aws-br-pic.kwai.net/bs2/overseaHead/20261008020943_BNTU4ODQzMDkz_t.jpg",
                          "display_name": "Kwai Brasil Oficial",
                          "id": "3xyutri4afq3qks",
                          "is_verified": true,
                          "url": "https://www.kwai.com/@KwaiBrasilOficial",
                          "username": "KwaiBrasilOficial"
                        },
                        "coauthors": [],
                        "duration_ms": 38666,
                        "hashtags": [
                          "MansãoDoPrêmioKwai"
                        ],
                        "id": "5217007328706437238",
                        "is_nsfw": null,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": null,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": 38666,
                            "expires_at": null,
                            "height": 1280,
                            "thumbnail_url": "https://p16-kimg.kwai.net/kimg/EKzM1y8qkAEKAnMzEg1waG90by1vdmVyc2VhGnt1cGljLzIwMjYvMTEvMDUvMDMvQk1qQXlOakV4TURVd016QXhOVGRmTlRVNE9EUXpNRGt6WHpFMU1ERXhNVFl5TkRnME1qQXlPRjh4WHpNPV9vdXVfQjAxZTZkOTg2Zjg3MmFjNjBhMTc4OTExZGI2NGY2NGViLndlYnA.webp",
                            "type": "video",
                            "url": "https://aws-br-cdn.kwai.net/upic/2026/11/05/03/BMjAyNjExMDUwMzAxNTdfNTU4ODQzMDkzXzE1MDExMTYyNDg0MjAyOF8xXzM=_b_B161359d1b4083988f2222d3700ae96d4.mp4?tag=1-1793835247-s-0-frvubdvelt-a6012d07ab30da3b",
                            "width": 720
                          }
                        ],
                        "mentions": [],
                        "metrics": {
                          "comment_count": 103,
                          "like_count": 1018,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": null,
                          "share_count": 105,
                          "view_count": 9137
                        },
                        "platform": "kwai",
                        "platform_specific": {
                          "kwai": {
                            "author_user_id": "558843093",
                            "author_verified_description": "Conta Oficial",
                            "category": "Dance",
                            "duet_source": null,
                            "is_ai_generated": false,
                            "music": null,
                            "place": null,
                            "subcategory": "Fashion dance",
                            "tagged_accounts": []
                          }
                        },
                        "platform_type": null,
                        "published_at": "2026-11-04T19:15:36Z",
                        "text": "SEGURA QUE É HIT! 🎶🔥 Aqui na #MansãoDoPrêmioKwai os criadores já estão entregando TU-DO! Grave seu vídeo usando o áudio oficial da Mansão que toda a turma de criadores está ansiosa pra te ver brilhando no Kwai! 😎",
                        "thumbnail_url": "https://p16-kimg.kwai.net/kimg/EKzM1y8qkAEKAnMzEg1waG90by1vdmVyc2VhGnt1cGljLzIwMjYvMTEvMDUvMDMvQk1qQXlOakV4TURVd016QXhOVGRmTlRVNE9EUXpNRGt6WHpFMU1ERXhNVFl5TkRnME1qQXlPRjh4WHpNPV9vdXVfQjAxZTZkOTg2Zjg3MmFjNjBhMTc4OTExZGI2NGY2NGViLndlYnA.webp",
                        "title": null,
                        "type": "video",
                        "unknown_fields": [],
                        "url": "https://www.kwai.com/@KwaiBrasilOficial/video/5217007328706437238"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "kwai",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1175,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "5217007328706437238",
                          "url": "https://www.kwai.com/@KwaiBrasilOficial/video/5217007328706437238"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/KwaiPostResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Short video file with exact views and likes",
        "tags": [
          "Kwai"
        ],
        "x-socialtap-endpoint": "kwai.post",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/kwai/posts": {
      "get": {
        "description": "Returns a public Kwai account's short videos, pinned first and then newest first, from its name, profile link or ID. Each video has its link, caption, hashtags, exact publish time and length, video file and cover, the sound with its audio file, the place and accounts tagged, Kwai's topic, and exact views, likes, comments and shares.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Post` items (the shared schema, the same on every platform), newest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/kwai/posts/ (Markdown: https://socialtap.dev/docs/reference/kwai/posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/kwai/posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/kwai/posts/"
        },
        "operationId": "kwai.posts.list",
        "parameters": [
          {
            "description": "The Kwai account: its name exactly as cased, with or without the @ (KwaiBrasilOficial), a profile link (kwai.com/@KwaiBrasilOficial), or its ID (3xyutri4afq3qks or 558843093).",
            "example": "KwaiBrasilOficial",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Kwai account: its name exactly as cased, with or without the @ (KwaiBrasilOficial), a profile link (kwai.com/@KwaiBrasilOficial), or its ID (3xyutri4afq3qks or 558843093).",
              "examples": [
                "KwaiBrasilOficial"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only posts published at or after this time. Ends the walk at the first older post (pinned posts don't end it).",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only posts published at or after this time. Ends the walk at the first older post (pinned posts don't end it).",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Only posts published before this time.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Only posts published before this time.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://aws-br-pic.kwai.net/bs2/overseaHead/20261008020943_BNTU4ODQzMDkz_tw.webp",
                            "display_name": "Kwai Brasil Oficial",
                            "id": "3xyutri4afq3qks",
                            "is_verified": true,
                            "url": "https://www.kwai.com/@KwaiBrasilOficial",
                            "username": "KwaiBrasilOficial"
                          },
                          "coauthors": [],
                          "duration_ms": 38666,
                          "hashtags": [
                            "MansãoDoPrêmioKwai"
                          ],
                          "id": "5217007328706437238",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 38666,
                              "expires_at": null,
                              "height": 1280,
                              "thumbnail_url": "https://p16-kimg.kwai.net/kimg/EKzM1y8qkAEKAnMzEg1waG90by1vdmVyc2VhGnt1cGljLzIwMjYvMTEvMDUvMDMvQk1qQXlOakV4TURVd016QXhOVGRmTlRVNE9EUXpNRGt6WHpFMU1ERXhNVFl5TkRnME1qQXlPRjh4WHpNPV9vdXVfQjAxZTZkOTg2Zjg3MmFjNjBhMTc4OTExZGI2NGY2NGViLndlYnA.webp",
                              "type": "video",
                              "url": "https://aws-br-cdn.kwai.net/upic/2026/11/05/03/BMjAyNjExMDUwMzAxNTdfNTU4ODQzMDkzXzE1MDExMTYyNDg0MjAyOF8xXzM=_b_B161359d1b4083988f2222d3700ae96d4.mp4?tag=1-1793830997-s-0-aft8a9zkaj-75bdcf472d005796",
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 70,
                            "like_count": 599,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": 62,
                            "view_count": 5456
                          },
                          "platform": "kwai",
                          "platform_specific": {
                            "kwai": {
                              "author_user_id": "558843093",
                              "author_verified_description": "Conta Oficial",
                              "category": "Dance",
                              "duet_source": null,
                              "is_ai_generated": null,
                              "music": null,
                              "place": null,
                              "subcategory": "Fashion dance",
                              "tagged_accounts": []
                            }
                          },
                          "platform_type": null,
                          "published_at": "2026-11-04T19:15:36Z",
                          "text": "SEGURA QUE É HIT! 🎶🔥 Aqui na #MansãoDoPrêmioKwai os criadores já estão entregando TU-DO! Grave seu vídeo usando o áudio oficial da Mansão que toda a turma de criadores está ansiosa pra te ver brilhando no Kwai! 😎",
                          "thumbnail_url": "https://p16-kimg.kwai.net/kimg/EKzM1y8qkAEKAnMzEg1waG90by1vdmVyc2VhGnt1cGljLzIwMjYvMTEvMDUvMDMvQk1qQXlOakV4TURVd016QXhOVGRmTlRVNE9EUXpNRGt6WHpFMU1ERXhNVFl5TkRnME1qQXlPRjh4WHpNPV9vdXVfQjAxZTZkOTg2Zjg3MmFjNjBhMTc4OTExZGI2NGY2NGViLndlYnA.webp",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.kwai.com/@KwaiBrasilOficial/video/5217007328706437238"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://aws-br-pic.kwai.net/bs2/overseaHead/20261008020943_BNTU4ODQzMDkz_tw.webp",
                            "display_name": "Kwai Brasil Oficial",
                            "id": "3xyutri4afq3qks",
                            "is_verified": true,
                            "url": "https://www.kwai.com/@KwaiBrasilOficial",
                            "username": "KwaiBrasilOficial"
                          },
                          "coauthors": [],
                          "duration_ms": 33900,
                          "hashtags": [
                            "PrêmioKwai2026",
                            "MansãoDoPrêmioKwai"
                          ],
                          "id": "5253036126006549807",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 33900,
                              "expires_at": null,
                              "height": 1280,
                              "thumbnail_url": "https://p16-kimg.kwai.net/kimg/EKzM1y8qkQEKAnMzEg1waG90by1vdmVyc2VhGnx1cGljLzIwMjYvMTEvMDQvMDUvQk1qQXlOakV4TURRd05UQTJOVFJmTlRVNE9EUXpNRGt6WHpFMU1ERXhNVFl5TURZek9ETTBOVjh6WHpNPV9vZmZuX0I3MzRlOWY5NTY5ZjAyZmZmZDVlYWU1OWQ3MGZmZTJhOS53ZWJw.webp",
                              "type": "video",
                              "url": "https://aws-br-cdn.kwai.net/upic/2026/11/04/05/BMjAyNjExMDQwNTA2NTRfNTU4ODQzMDkzXzE1MDExMTYyMDYzODM0NV8zXzM=_b_Bf9a7e69ab39d2f43b43438499d208145.mp4?tag=1-1793830997-s-0-nmjymrllbn-df8c5e0494c31d90",
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 31,
                            "like_count": 368,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": 28,
                            "view_count": 8060
                          },
                          "platform": "kwai",
                          "platform_specific": {
                            "kwai": {
                              "author_user_id": "558843093",
                              "author_verified_description": "Conta Oficial",
                              "category": "Scripted Drama",
                              "duet_source": null,
                              "is_ai_generated": null,
                              "music": {
                                "author_name": "Kwai Brasil Oficial",
                                "cover_url": null,
                                "duration_ms": 33000,
                                "id": "13776648614",
                                "is_original": true,
                                "play_url": "https://aws-br-pic.kwai.net/bs2/ost/MTUwMTExNjIwNjM4MzQ1XzU1ODg0MzA5Mw.m4a",
                                "title": null
                              },
                              "place": null,
                              "subcategory": null,
                              "tagged_accounts": []
                            }
                          },
                          "platform_type": null,
                          "published_at": "2026-11-04T12:30:01Z",
                          "text": "O QUE SERÁ QUE TÁ ROLANDO? 🕵️‍♂️🔥 Os indicados ao #PrêmioKwai2026 foram convocados para uma missão secreta! Assista aos próximos episódios e acompanhe tudo por aqui! ✨ #MansãoDoPrêmioKwai",
                          "thumbnail_url": "https://p16-kimg.kwai.net/kimg/EKzM1y8qkQEKAnMzEg1waG90by1vdmVyc2VhGnx1cGljLzIwMjYvMTEvMDQvMDUvQk1qQXlOakV4TURRd05UQTJOVFJmTlRVNE9EUXpNRGt6WHpFMU1ERXhNVFl5TURZek9ETTBOVjh6WHpNPV9vZmZuX0I3MzRlOWY5NTY5ZjAyZmZmZDVlYWU1OWQ3MGZmZTJhOS53ZWJw.webp",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.kwai.com/@KwaiBrasilOficial/video/5253036126006549807"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://aws-br-pic.kwai.net/bs2/overseaHead/20261008020943_BNTU4ODQzMDkz_tw.webp",
                            "display_name": "Kwai Brasil Oficial",
                            "id": "3xyutri4afq3qks",
                            "is_verified": true,
                            "url": "https://www.kwai.com/@KwaiBrasilOficial",
                            "username": "KwaiBrasilOficial"
                          },
                          "coauthors": [],
                          "duration_ms": 15835,
                          "hashtags": [
                            "MansãoDoPrêmioKwai",
                            "PrêmioKwai2026"
                          ],
                          "id": "5226014528525626248",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 15835,
                              "expires_at": null,
                              "height": 1280,
                              "thumbnail_url": "https://p1-kimg.kwai.net/kimg/EKzM1y8qkAEKAnMzEg1waG90by1vdmVyc2VhGnt1cGljLzIwMjYvMTEvMDIvMDIvQk1qQXlOakV4TURJd01qRTVNekJmTlRVNE9EUXpNRGt6WHpFMU1ERXhNVFl4TURnek56UTJNbDh4WHpNPV9vdXVfQmY3MmU1YzlhNTFkNTQ2MjU5YzYwNjgyOTQwZGU0YzVlLndlYnA.webp",
                              "type": "video",
                              "url": "https://aws-br-cdn.kwai.net/upic/2026/11/02/02/BMjAyNjExMDIwMjE5MzBfNTU4ODQzMDkzXzE1MDExMTYxMDgzNzQ2Ml8xXzM=_b_Bbcc2909a557c0eabb78691e0e9c59282.mp4?tag=1-1793830997-s-0-mgawyk5jvt-2bebbe52da97c828",
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 175,
                            "like_count": 1619,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": 114,
                            "view_count": 32202
                          },
                          "platform": "kwai",
                          "platform_specific": {
                            "kwai": {
                              "author_user_id": "558843093",
                              "author_verified_description": "Conta Oficial",
                              "category": "Entertainment",
                              "duet_source": null,
                              "is_ai_generated": null,
                              "music": {
                                "author_name": "Kwai Brasil Oficial",
                                "cover_url": null,
                                "duration_ms": 15000,
                                "id": "13768366147",
                                "is_original": true,
                                "play_url": "https://aws-br-pic.kwai.net/bs2/ost/MTUwMTExNjEwODM3NDYyXzU1ODg0MzA5Mw.m4a",
                                "title": null
                              },
                              "place": null,
                              "subcategory": "Gossip&celebrity",
                              "tagged_accounts": []
                            }
                          },
                          "platform_type": null,
                          "published_at": "2026-11-01T18:19:44Z",
                          "text": "Se liga no que vem por aí… 👀 A #MansãoDoPrêmioKwai já está pronta e promete entregar puro suco de caos e diversão com um elenco de peso: os indicados à categoria Criador do Ano do #PrêmioKwai2026! 🏆 Fica de olho na página no app, porque logo menos a #MansãoDoPrêmioKwai vai invadi…",
                          "thumbnail_url": "https://p1-kimg.kwai.net/kimg/EKzM1y8qkAEKAnMzEg1waG90by1vdmVyc2VhGnt1cGljLzIwMjYvMTEvMDIvMDIvQk1qQXlOakV4TURJd01qRTVNekJmTlRVNE9EUXpNRGt6WHpFMU1ERXhNVFl4TURnek56UTJNbDh4WHpNPV9vdXVfQmY3MmU1YzlhNTFkNTQ2MjU5YzYwNjgyOTQwZGU0YzVlLndlYnA.webp",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.kwai.com/@KwaiBrasilOficial/video/5226014528525626248"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "kwai",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1060,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "3xyutri4afq3qks",
                          "url": "https://www.kwai.com/@KwaiBrasilOficial"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/KwaiPostsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "User videos with exact views, likes and shares",
        "tags": [
          "Kwai"
        ],
        "x-socialtap-endpoint": "kwai.posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/kwai/profile": {
      "get": {
        "description": "Returns a public Kwai profile from its name, profile link or ID, with exact follower, following, post and like counts. It also has both forms of its ID, the name, bio, picture, verified badge with Kwai's label for it, the likes it has given, when it was created, and Kwai's word for what it posts.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/kwai/profile/ (Markdown: https://socialtap.dev/docs/reference/kwai/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/kwai/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/kwai/profile/"
        },
        "operationId": "kwai.profile.get",
        "parameters": [
          {
            "description": "The Kwai account: its name exactly as cased, with or without the @ (KwaiBrasilOficial), a profile link (kwai.com/@KwaiBrasilOficial), or its ID (3xyutri4afq3qks or 558843093).",
            "example": "https://www.kwai.com/@LEOZINW",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Kwai account: its name exactly as cased, with or without the @ (KwaiBrasilOficial), a profile link (kwai.com/@KwaiBrasilOficial), or its ID (3xyutri4afq3qks or 558843093).",
              "examples": [
                "KwaiBrasilOficial"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://aws-br-pic.kwai.net/bs2/overseaHead/20230726193222_BMTUwMDAwMTEyOTI2MTgy_s.jpg",
                        "banner_url": null,
                        "bio": "PERFIL OFICIAL: leozin w \n📍Manaus/ AM\no senhor é meu pastor e nada me faltará 🙏",
                        "category": "comedy",
                        "country_code": null,
                        "created_at": "2020-08-19T06:01:33Z",
                        "display_name": "LEOZIN W",
                        "external_links": [],
                        "id": "3xmf6xy6k7qsn7i",
                        "is_private": false,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 3485388,
                          "following_count": 598,
                          "post_count": 9824,
                          "total_like_count": 127821389,
                          "total_view_count": null
                        },
                        "platform": "kwai",
                        "platform_specific": {
                          "kwai": {
                            "gender": "M",
                            "is_banned": false,
                            "likes_given_count": 23571,
                            "playlist_count": 569,
                            "private_post_count": 0,
                            "user_id": "150000112926182",
                            "verified_description": "Criador(a) de Comédia",
                            "verified_type": 2
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://www.kwai.com/@LEOZINW",
                        "username": "LEOZINW"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "kwai",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1000,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "3xmf6xy6k7qsn7i",
                          "url": "https://www.kwai.com/@LEOZINW"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/KwaiProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact follower, like and post counts, and bio",
        "tags": [
          "Kwai"
        ],
        "x-socialtap-endpoint": "kwai.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/linkbio/profile": {
      "get": {
        "description": "Returns a public Lnk.Bio profile with every link in its list, even those the page loads as you scroll, and its social icons, emails and phones. It also has the name, bio, picture and verified badge, the @name under the picture (usually the Instagram username), the place a map block shows, the account's own domain and how many links the list holds. Send the page's name or link.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/linkbio/profile/ (Markdown: https://socialtap.dev/docs/reference/linkbio/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/linkbio/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/linkbio/profile/"
        },
        "operationId": "linkbio.profile.get",
        "parameters": [
          {
            "description": "The Lnk.Bio page: its name (msjennafischer, with or without the @) or its link (https://lnk.bio/msjennafischer).",
            "example": "msjennafischer",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Lnk.Bio page: its name (msjennafischer, with or without the @) or its link (https://lnk.bio/msjennafischer).",
              "examples": [
                "msjennafischer"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://s3.us-west-2.amazonaws.com/cdn.lnk.bio/profilepics/-1154992_20210503548.jpg",
                        "banner_url": null,
                        "bio": null,
                        "category": null,
                        "country_code": null,
                        "created_at": null,
                        "display_name": null,
                        "external_links": [
                          {
                            "title": "@msjennafischer",
                            "url": "https://www.instagram.com/msjennafischer"
                          },
                          {
                            "title": "From “The Office” to Cancer Survivor and Advocate",
                            "url": "https://www.futureofpersonalhealth.com/campaign/cancer-care/"
                          },
                          {
                            "title": "Office Ladies Merch",
                            "url": "http://shopofficeladies.com/"
                          }
                        ],
                        "id": "-1154992",
                        "is_private": false,
                        "is_verified": false,
                        "location": null,
                        "metrics": {
                          "follower_count": null,
                          "following_count": null,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "linkbio",
                        "platform_specific": {
                          "linkbio": {
                            "custom_domain_url": null,
                            "emails": [],
                            "link_count": 10,
                            "linked_username": "msjennafischer",
                            "phones": [],
                            "social_links": []
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://lnk.bio/msjennafischer",
                        "username": "msjennafischer"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "linkbio",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 422,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "-1154992",
                          "url": "https://lnk.bio/msjennafischer"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/LinkbioProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Link list, social icons, emails and phone numbers",
        "tags": [
          "Lnk.Bio"
        ],
        "x-socialtap-endpoint": "linkbio.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/linkedin/ad": {
      "get": {
        "description": "Returns one ad from LinkedIn's public Ad Library, in any format, from its link or ID: advertiser, who paid, text, media and destination. You also get the headline and call to action, the member a promoted post appears from, the video file, every carousel slide, a document's first pages, a message ad's sender and buttons, and a job's or event's details. Ads shown in the EU and Brazil add their run dates, an impressions range, each country's share of it and the targeting.\n\nReturns `{data, meta}`: `data` is a `Ad` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/linkedin/ad/ (Markdown: https://socialtap.dev/docs/reference/linkedin/ad/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/linkedin/ad/index.md)",
          "url": "https://socialtap.dev/docs/reference/linkedin/ad/"
        },
        "operationId": "linkedin.ad.get",
        "parameters": [
          {
            "description": "A LinkedIn Ad Library ad: its link (linkedin.com/ad-library/detail/<id>), a company discovery ad's (linkedin.com/ad-library/employer-brand/<id>?talentMarketplaceChannelId=<n>), or its ID alone.",
            "example": "https://www.linkedin.com/ad-library/detail/1618054634",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "A LinkedIn Ad Library ad: its link (linkedin.com/ad-library/detail/<id>), a company discovery ad's (linkedin.com/ad-library/employer-brand/<id>?talentMarketplaceChannelId=<n>), or its ID alone.",
              "examples": [
                "https://www.linkedin.com/ad-library/detail/1603768123"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "advertiser": {
                          "avatar_url": "https://media.licdn.com/dms/image/v2/D4E0BAQHUYDHTOOXs9w/company-logo_100_100/B4EZ8eP9xVIkAI-/0/1782918929735/mckinsey_logo?e=1795651200&v=beta&t=WbmINHi9RwK4JEWEBaGhPYl0CZQ41Gx2fC_wV7PTGMQ",
                          "display_name": "McKinsey & Company",
                          "id": "1371",
                          "is_verified": null,
                          "url": "https://www.linkedin.com/company/1371",
                          "username": null
                        },
                        "approximate_fields": [
                          "first_shown_at",
                          "impressions",
                          "last_shown_at"
                        ],
                        "audience_size": null,
                        "country_codes": [
                          "AD",
                          "AE",
                          "AF"
                        ],
                        "creatives": [
                          {
                            "body": "COP31 will bring together global leaders at an important moment for the energy transition and sustainability, as growing energy demand, advancing climate technologies, and the need for greater resilience create new opportunities for businesses and investors. In Antalya, Turkey, M…",
                            "cta_text": "Register",
                            "link_description": null,
                            "link_url": "https://www.mckinsey.com/capabilities/sustainability/how-we-help-clients/cop/agenda?cid=pls-pso-lkn-mbm-register2-cop-glb-cxo-mst",
                            "media": [
                              {
                                "alt_text": "See our full COP31 program",
                                "duration_ms": null,
                                "expires_at": null,
                                "height": null,
                                "thumbnail_url": null,
                                "type": "image",
                                "url": "https://media.licdn.com/dms/image/v2/D4E10AQGIL3fJ7ZL76g/image-shrink_1280/B4EaGIprtMIgAc-/0/1793293991306/McKatCOP31Generic1920x1920pxpng?e=2147483647&v=beta&t=QNkoQzYbKqcN23t1ljf805eo4_IJRngJlRR5KoxFexU",
                                "width": null
                              }
                            ],
                            "title": "See our full COP31 program"
                          }
                        ],
                        "first_shown_at": "2026-10-30T00:00:00Z",
                        "id": "1618054634",
                        "impressions": {
                          "lower_bound": 5000,
                          "upper_bound": 10000
                        },
                        "is_active": null,
                        "is_political": null,
                        "languages": [],
                        "last_shown_at": "2026-10-30T00:00:00Z",
                        "paid_by": "Mckinsey & Company, Inc.",
                        "platform": "linkedin",
                        "platform_specific": {
                          "linkedin": {
                            "company": null,
                            "creative_type": "SPONSORED_STATUS_UPDATE",
                            "document": null,
                            "event": null,
                            "format": "Single Image Ad",
                            "impressions_by_country": [
                              {
                                "country": "Pakistan",
                                "country_code": "PK",
                                "is_under_one_percent": false,
                                "share_percent": 17
                              },
                              {
                                "country": "Turkey",
                                "country_code": "TR",
                                "is_under_one_percent": false,
                                "share_percent": 8
                              },
                              {
                                "country": "Bangladesh",
                                "country_code": "BD",
                                "is_under_one_percent": false,
                                "share_percent": 4
                              }
                            ],
                            "is_deleted": false,
                            "job": null,
                            "message": null,
                            "newsletter": null,
                            "poster": {
                              "avatar_url": "https://media.licdn.com/dms/image/v2/D4E0BAQHUYDHTOOXs9w/company-logo_100_100/B4EZ8eP9xVIkAI-/0/1782918929735/mckinsey_logo?e=1795651200&v=beta&t=WbmINHi9RwK4JEWEBaGhPYl0CZQ41Gx2fC_wV7PTGMQ",
                              "display_name": "McKinsey & Company",
                              "id": "1371",
                              "is_verified": null,
                              "url": "https://www.linkedin.com/company/1371",
                              "username": null
                            },
                            "poster_title": null,
                            "targeting": {
                              "audience": {
                                "is_excluded": true,
                                "is_targeted": false
                              },
                              "company": {
                                "is_excluded": false,
                                "is_targeted": false
                              },
                              "demographic": {
                                "is_excluded": false,
                                "is_targeted": false
                              },
                              "education": {
                                "is_excluded": false,
                                "is_targeted": false
                              },
                              "job": {
                                "is_excluded": false,
                                "is_targeted": true
                              },
                              "languages": {
                                "excluded": [],
                                "included": [
                                  "English"
                                ]
                              },
                              "locations": {
                                "excluded": [
                                  "India"
                                ],
                                "included": [
                                  "Türkiye",
                                  "Asia",
                                  "Europe"
                                ]
                              },
                              "member_interests": {
                                "is_excluded": false,
                                "is_targeted": true
                              }
                            }
                          }
                        },
                        "publisher_platforms": [],
                        "reach": null,
                        "spend": null,
                        "type": "image",
                        "unknown_fields": [
                          "languages",
                          "publisher_platforms"
                        ],
                        "url": "https://www.linkedin.com/ad-library/detail/1618054634"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "linkedin",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 559,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "ad",
                          "id": "1618054634",
                          "url": "https://www.linkedin.com/ad-library/detail/1618054634"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/LinkedinAdResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Creative, payer and EU targeting, in any format",
        "tags": [
          "LinkedIn Ad Library"
        ],
        "x-socialtap-endpoint": "linkedin.ad",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "ad",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/linkedin/post": {
      "get": {
        "description": "Returns a public LinkedIn post or Pulse article from its link, URN or activity ID, with exact reaction and comment counts and its top comments. You also get the text with hashtags and mentions, the exact publish time, the author (member or Page) with their headline and follower count, images, the native video file, a document's pages, the link card and the post a reshare quotes. An article adds its full body, cover image, last edit and the author's other articles.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/linkedin/post/ (Markdown: https://socialtap.dev/docs/reference/linkedin/post/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/linkedin/post/index.md)",
          "url": "https://socialtap.dev/docs/reference/linkedin/post/"
        },
        "operationId": "linkedin.post.get",
        "parameters": [
          {
            "description": "A LinkedIn post or article: a post's link as the share menu gives it (linkedin.com/posts/<author>_<slug>-activity-<id>-<code>), its feed or embed link (linkedin.com/feed/update/urn:li:activity:<id>, also urn:li:share: and urn:li:ugcPost:), an article's (linkedin.com/pulse/<slug>), on any country host, or a post's bare URN (urn:li:activity:<id>) or activity ID.",
            "example": "https://www.linkedin.com/feed/update/urn:li:activity:7522801130767224832/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "A LinkedIn post or article: a post's link as the share menu gives it (linkedin.com/posts/<author>_<slug>-activity-<id>-<code>), its feed or embed link (linkedin.com/feed/update/urn:li:activity:<id>, also urn:li:share: and urn:li:ugcPost:), an article's (linkedin.com/pulse/<slug>), on any country host, or a post's bare URN (urn:li:activity:<id>) or activity ID.",
              "examples": [
                "https://www.linkedin.com/feed/update/urn:li:activity:7522801130767224832"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://media.licdn.com/dms/image/v2/D5603AQF-RYZP55jmXA/profile-displayphoto-shrink_400_400/B56ZRi8g.aGsAg-/0/1736826818802?e=2147483647&v=beta&t=r6LJYwKPrJzfFDXVG8qAOoklQnqvEN855sHJ1NxhEAo",
                          "display_name": "Bill Gates",
                          "id": null,
                          "is_verified": null,
                          "url": "https://www.linkedin.com/in/williamhgates",
                          "username": "williamhgates"
                        },
                        "coauthors": [],
                        "duration_ms": null,
                        "hashtags": [],
                        "id": "7522801130767224832",
                        "is_nsfw": null,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": null,
                        "media": [],
                        "mentions": [],
                        "metrics": {
                          "comment_count": 242,
                          "like_count": 1344,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": null,
                          "share_count": null,
                          "view_count": null
                        },
                        "platform": "linkedin",
                        "platform_specific": {
                          "linkedin": {
                            "author_follower_count": 40785228,
                            "author_headline": "Chair, Gates Foundation and Founder, Breakthrough Energy",
                            "content_urn": "urn:li:share:7522801130179837952",
                            "document": null,
                            "hidden_image_count": null,
                            "is_author_influencer": true,
                            "is_edited": true,
                            "link": {
                              "image_url": "https://media.licdn.com/dms/image/sync/v2/D4E27AQFkOX_Yu-a3fA/articleshare-shrink_800/B4EaFOeCzFLEAc-/0/1792317861513?e=2147483647&v=beta&t=qdrGnTqb_PQ04rvZTnnwoc3rZ4giI_-1g2TBBvB65IM",
                              "source": "theguardian.com",
                              "title": "World Bank says ‘small AI’ could transform developing countries",
                              "url": "https://www.theguardian.com/technology/2026/oct/18/world-bank-artificial-intelligence-developing-economies"
                            },
                            "modified_at": null,
                            "more_articles": [],
                            "repost_activity_id": null,
                            "reshared_post": null,
                            "top_comments": [
                              {
                                "author": {
                                  "avatar_url": null,
                                  "display_name": "Cristian Perez Añasco",
                                  "id": null,
                                  "is_verified": null,
                                  "url": "https://www.linkedin.com/in/cristian-perez-a%C3%B1asco-87a11740",
                                  "username": "cristian-perez-añasco-87a11740"
                                },
                                "id": "7522806165316210688",
                                "like_count": 49,
                                "published_at": "2026-11-01T23:45:56Z",
                                "text": "What Bill Gates points to is already scaling in India with measurable numbers. MahaVISTAAR-AI under MahaAgri-AI policy crossed 3 million downloads in months and portable soil testing using hyperspectral imaging delivers full chemical profile with over 90 percent accuracy. All run…"
                              },
                              {
                                "author": {
                                  "avatar_url": "https://media.licdn.com/dms/image/v2/D5603AQFJhAiszj4Vmg/profile-displayphoto-scale_400_400/B56aGi12q6K8Ak-/0/1793733390035?e=2147483647&v=beta&t=KBT6MVpk5Bh7XGkE-G3cBKFsdxm7b9Yt86yyvQ1zwWM",
                                  "display_name": "Chris Black",
                                  "id": null,
                                  "is_verified": null,
                                  "url": "https://www.linkedin.com/in/chris-black-yyc",
                                  "username": "chris-black-yyc"
                                },
                                "id": "7523029437056114688",
                                "like_count": 6,
                                "published_at": "2026-11-02T14:33:08Z",
                                "text": "The phone already in their pocket is what got me. A farmer gets an answer in their own language without buying anything new."
                              },
                              {
                                "author": {
                                  "avatar_url": null,
                                  "display_name": "Henrik Pålsson",
                                  "id": null,
                                  "is_verified": null,
                                  "url": "https://www.linkedin.com/in/henrik-p%C3%A5lsson-278659",
                                  "username": "henrik-pålsson-278659"
                                },
                                "id": "7522804034852855808",
                                "like_count": 5,
                                "published_at": "2026-11-01T23:37:28Z",
                                "text": "100% agree, but The Road Ahead has rather more bends than we imagined when we met in Stockholm 30 years ago. Perhaps the map was folded. 😉"
                              }
                            ]
                          }
                        },
                        "platform_type": "post",
                        "published_at": "2026-11-01T23:25:56Z",
                        "text": "Useful advice for farmers, in their own language, on a phone they already have in their pocket. That’s the type of AI I’m excited about.",
                        "thumbnail_url": "https://media.licdn.com/dms/image/sync/v2/D4E27AQFkOX_Yu-a3fA/articleshare-shrink_800/B4EaFOeCzFLEAc-/0/1792317861513?e=2147483647&v=beta&t=qdrGnTqb_PQ04rvZTnnwoc3rZ4giI_-1g2TBBvB65IM",
                        "title": "World Bank says ‘small AI’ could transform developing countries",
                        "type": "link",
                        "unknown_fields": [],
                        "url": "https://www.linkedin.com/feed/update/urn:li:activity:7522801130767224832"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "linkedin",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 703,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "7522801130767224832",
                          "url": "https://www.linkedin.com/feed/update/urn:li:activity:7522801130767224832"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/LinkedinPostResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Post or article with exact reactions and comments",
        "tags": [
          "LinkedIn"
        ],
        "x-socialtap-endpoint": "linkedin.post",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/linkedin/profile": {
      "get": {
        "description": "Returns a public LinkedIn company, school or showcase Page, or a member's profile, from its link or its name with a prefix (company/, in/). A Page has its industry, size, headquarters and locations, website, founding year, specialties, exact follower and employee counts, and the affiliated and similar Pages beside it. A member has their headline, about text, location, followers, connections, experience, education, skills, certifications, projects, publications, recommendations and the other sections their public profile lists.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit (public page or web search) or 5 credits (data partner) per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/linkedin/profile/ (Markdown: https://socialtap.dev/docs/reference/linkedin/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/linkedin/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/linkedin/profile/"
        },
        "operationId": "linkedin.profile.get",
        "parameters": [
          {
            "description": "The LinkedIn account: a Page's link (linkedin.com/company/<name>, /school/<name>, /showcase/<name>, any tab of it) or a member's (linkedin.com/in/<name>), or its name with the prefix that says which (company/google, school/mit, showcase/microsoft-security, in/williamhgates). A bare name is a company's; LinkedIn leads a company name to the school or showcase page of that name. Names are case-insensitive.",
            "example": "https://ca.linkedin.com/company/shopify",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The LinkedIn account: a Page's link (linkedin.com/company/<name>, /school/<name>, /showcase/<name>, any tab of it) or a member's (linkedin.com/in/<name>), or its name with the prefix that says which (company/google, school/mit, showcase/microsoft-security, in/williamhgates). A bare name is a company's; LinkedIn leads a company name to the school or showcase page of that name. Names are case-insensitive.",
              "examples": [
                "https://www.linkedin.com/company/microsoft/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://media.licdn.com/dms/image/v2/D560BAQG_KjTcNcrLVw/company-logo_200_200/B56ZZolTV.HUAU-/0/1745511331439/shopify_logo?e=2147483647&v=beta&t=D2saVg58cKnwEiDQgFgzvwL24mTRM_cPuU1ndv6kL2U",
                        "banner_url": "https://media.licdn.com/dms/image/v2/D563DAQEzTxxoWnXuew/image-scale_325_1920/B56aE7BBZdKgAI-/0/1791991486349/shopify_cover?e=2147483647&v=beta&t=b2AsimBH6u_xrudtlChar7RG3u83yzSxztJZvnV10HM",
                        "bio": "Shopify is a leading global commerce company, providing trusted tools to start, grow, market, and manage a retail business of any size. Shopify makes commerce better for everyone with a platform and services that are engineered for reliability, while delivering a better shopping …",
                        "category": "Software Development",
                        "country_code": "CA",
                        "created_at": null,
                        "display_name": "Shopify",
                        "external_links": [
                          {
                            "title": null,
                            "url": "https://www.shopify.com"
                          }
                        ],
                        "id": "784652",
                        "is_private": false,
                        "is_verified": null,
                        "location": "Ottawa, ON",
                        "metrics": {
                          "follower_count": 1119403,
                          "following_count": null,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "linkedin",
                        "platform_specific": {
                          "linkedin": {
                            "affiliated_pages": [
                              {
                                "avatar_url": "https://media.licdn.com/dms/image/v2/D4E0BAQEHykfrk07ZCQ/company-logo_100_100/company-logo_100_100/0/1726856574825?e=2147483647&v=beta&t=40c3dGLlHhLuZvUGFzWKv8ef2JQ6eVEeAv7Q3z54b8A",
                                "category": "Venture Capital and Private Equity Principals",
                                "display_name": "Shopify Ventures",
                                "id": null,
                                "is_verified": null,
                                "location": null,
                                "url": "https://www.linkedin.com/showcase/shopify-ventures",
                                "username": "shopify-ventures"
                              }
                            ],
                            "certifications": [],
                            "company_size": {
                              "lower_bound": 10001,
                              "upper_bound": null
                            },
                            "connection_count": null,
                            "courses": [],
                            "education": [],
                            "employee_count": 30322,
                            "employees": [
                              {
                                "avatar_url": "https://media.licdn.com/dms/image/v2/C4E03AQFUruTJfTC02Q/profile-displayphoto-shrink_100_100/profile-displayphoto-shrink_100_100/0/1516156085586?e=2147483647&v=beta&t=Axi-4iq0uAVwIj4N9E8SUHZwcmX77p9pet5Ri2m1GLM",
                                "display_name": "Sam Ruby",
                                "id": null,
                                "is_verified": null,
                                "url": "https://www.linkedin.com/in/saruby",
                                "username": "saruby"
                              },
                              {
                                "avatar_url": "https://media.licdn.com/dms/image/v2/C5603AQG6JPHHDSVF_g/profile-displayphoto-shrink_100_100/profile-displayphoto-shrink_100_100/0/1600306045236?e=2147483647&v=beta&t=SYwM63n268TcHjRQFbsz1EXXcGkXxKnYKNqNVUwDjA8",
                                "display_name": "Joseph Smarr",
                                "id": null,
                                "is_verified": null,
                                "url": "https://www.linkedin.com/in/jsmarr",
                                "username": "jsmarr"
                              },
                              {
                                "avatar_url": "https://media.licdn.com/dms/image/v2/D5603AQHzy24GWVgpWQ/profile-displayphoto-shrink_100_100/profile-displayphoto-shrink_100_100/0/1672455361616?e=2147483647&v=beta&t=rxjMeSkOWQYUTo4BYQiTn8CVlNlfbtuRgHO3zDQaSRg",
                                "display_name": "Todd Muchmore",
                                "id": null,
                                "is_verified": null,
                                "url": "https://www.linkedin.com/in/toddmuchmore",
                                "username": "toddmuchmore"
                              }
                            ],
                            "experience": [],
                            "founded_year": 2006,
                            "headline": null,
                            "headquarters": {
                              "city": "Ottawa",
                              "country_code": "CA",
                              "postal_code": null,
                              "region": "ON",
                              "street": null
                            },
                            "honors": [],
                            "is_creator": null,
                            "is_hiring": null,
                            "is_influencer": null,
                            "is_open_to_work": null,
                            "kind": "company",
                            "languages": [],
                            "locations": [
                              {
                                "address": "Ottawa, ON, CA",
                                "is_primary": true
                              }
                            ],
                            "organization_type": "Public Company",
                            "organizations": [],
                            "patents": [],
                            "projects": [],
                            "publications": [],
                            "recommendation_count": null,
                            "recommendations": [],
                            "similar_pages": [
                              {
                                "avatar_url": "https://media.licdn.com/dms/image/v2/D560BAQE2ZfJyfn-VCg/company-logo_100_100/B56ZlyKwpUKIAQ-/0/1758557047806/stripe_logo?e=2147483647&v=beta&t=fRMcaMGPJNFUMq_l1f2zzyX4PaK3yg-MRicyUuY3qSI",
                                "category": "Technology, Information and Internet",
                                "display_name": "Stripe",
                                "id": null,
                                "is_verified": null,
                                "location": "South San Francisco, California",
                                "url": "https://www.linkedin.com/company/stripe",
                                "username": "stripe"
                              },
                              {
                                "avatar_url": "https://media.licdn.com/dms/image/v2/C560BAQFkDzx_7dqq3A/company-logo_100_100/company-logo_100_100/0/1631377935713?e=2147483647&v=beta&t=AiRi3YW2R5kYKHbxsjkdQ_d1RuH6Yk98ePBwANPPDhc",
                                "category": "Musicians",
                                "display_name": "Spotify",
                                "id": null,
                                "is_verified": null,
                                "location": "Stockholm, Stockholm County",
                                "url": "https://www.linkedin.com/company/spotify",
                                "username": "spotify"
                              },
                              {
                                "avatar_url": "https://media.licdn.com/dms/image/v2/C560BAQFhfl32crIGIw/company-logo_100_100/company-logo_100_100/0/1630637496980/airbnb_logo?e=2147483647&v=beta&t=idNQqoBZi6dZq6iG78J5GTOsNV_ltJf7ITo7zYZ6VWg",
                                "category": "Software Development",
                                "display_name": "Airbnb",
                                "id": null,
                                "is_verified": null,
                                "location": "San Francisco, CA",
                                "url": "https://www.linkedin.com/company/airbnb",
                                "username": "airbnb"
                              }
                            ],
                            "similar_profiles": [],
                            "skills": [],
                            "specialties": [
                              "ecommerce",
                              "API",
                              "applications"
                            ],
                            "tagline": "Make commerce better for everyone",
                            "volunteering": []
                          }
                        },
                        "type": "organization",
                        "unknown_fields": [],
                        "url": "https://www.linkedin.com/company/shopify",
                        "username": "shopify"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "linkedin",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1175,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "784652",
                          "url": "https://www.linkedin.com/company/shopify"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/LinkedinProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Company size and industry, or a member's career",
        "tags": [
          "LinkedIn"
        ],
        "x-socialtap-endpoint": "linkedin.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 5,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            },
            {
              "credits": 5,
              "label": "5 credits",
              "max": 5,
              "per": 0,
              "source": "vendor"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "web_search"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/linkedin/search_ads": {
      "get": {
        "description": "Searches LinkedIn's public Ad Library for ads by keyword, advertiser name, company ID or payer, filtered by country and the days they ran. Each result is the library's card: the ad's ID and link, advertiser name and logo, format, headline, the start of its text, images, a video's cover, carousel slides and a document's first pages. Results come newest or oldest first, and the LinkedIn Ad Library Ad API returns any of them in full from its ID.\n\nReturns `{data, page, meta}`: `data` holds up to 24 `Ad` items (the shared schema, the same on every platform), most recently started first with sort=newest (the default), earliest started first with sort=oldest. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/linkedin/search_ads/ (Markdown: https://socialtap.dev/docs/reference/linkedin/search_ads/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/linkedin/search_ads/index.md)",
          "url": "https://socialtap.dev/docs/reference/linkedin/search_ads/"
        },
        "operationId": "linkedin.search_ads.list",
        "parameters": [
          {
            "description": "What to search for, as search_by says: words in the ad (keyword); words in the advertiser's name (advertiser), fuzzy, so other companies with those words come too; a company's numeric ID, or several with commas (advertiser_id), exact; words in the ad's \"Paid for by\" line (payer).",
            "example": "hiring",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to search for, as search_by says: words in the ad (keyword); words in the advertiser's name (advertiser), fuzzy, so other companies with those words come too; a company's numeric ID, or several with commas (advertiser_id), exact; words in the ad's \"Paid for by\" line (payer).",
              "examples": [
                "hiring"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "What query names. Default: keyword.",
            "example": "",
            "in": "query",
            "name": "search_by",
            "schema": {
              "default": "keyword",
              "description": "What query names. Default: keyword.",
              "enum": [
                "keyword",
                "advertiser",
                "advertiser_id",
                "payer"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only ads of advertisers with these words in their name, for a keyword or payer search. Fuzzy, like search_by=advertiser: other companies with those words come too. Use this or advertiser_id, not both.",
            "example": "",
            "in": "query",
            "name": "advertiser",
            "schema": {
              "description": "Only ads of advertisers with these words in their name, for a keyword or payer search. Fuzzy, like search_by=advertiser: other companies with those words come too. Use this or advertiser_id, not both.",
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Only this company's ads, for a keyword or payer search: its numeric ID, several with commas, or its link by ID (advertiser.url from the LinkedIn Ad Library Ad API, linkedin.com/company/1035). Exact. The LinkedIn Profile API returns a company's ID from its name.",
            "example": "1035",
            "in": "query",
            "name": "advertiser_id",
            "schema": {
              "description": "Only this company's ads, for a keyword or payer search: its numeric ID, several with commas, or its link by ID (advertiser.url from the LinkedIn Ad Library Ad API, linkedin.com/company/1035). Exact. The LinkedIn Profile API returns a company's ID from its name.",
              "examples": [
                "1035"
              ],
              "maxLength": 500,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only ads shown in this country. All countries when omitted.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). Only ads shown in this country. All countries when omitted.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only ads shown in any of these countries: ISO 3166-1 alpha-2 codes with commas. Use this or country, not both.",
            "example": "DE,FR",
            "in": "query",
            "name": "countries",
            "schema": {
              "description": "Only ads shown in any of these countries: ISO 3166-1 alpha-2 codes with commas. Use this or country, not both.",
              "examples": [
                "DE,FR"
              ],
              "maxLength": 750,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. newest: the ads that started most recently first, the library's default. oldest: the earliest first.",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "newest",
              "description": "Order of the results. newest: the ads that started most recently first, the library's default. oldest: the earliest first.",
              "enum": [
                "newest",
                "oldest"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Ads count when they ran during the window: an ad that last ran before this day is left out. LinkedIn searches whole days from about a year ago to about two days ago: 364 days back and three days back are always accepted, and past the limit, which moves with the hour, it is refused with the exact date, not answered empty. A window ends yesterday or the day before, so the newest ads are only found without since and until.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Ads count when they ran during the window: an ad that last ran before this day is left out. LinkedIn searches whole days from about a year ago to about two days ago: 364 days back and three days back are always accepted, and past the limit, which moves with the hour, it is refused with the exact date, not answered empty. A window ends yesterday or the day before, so the newest ads are only found without since and until.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Ads count when they ran during the window: an ad that first ran on or after this day is left out. An until past the last day LinkedIn's dates reach, yesterday or the day before, reads as that day. Alone, it starts the window about a year back, as far as LinkedIn's dates reach, so an ad that last ran before then is left out.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Ads count when they ran during the window: an ad that first ran on or after this day is left out. An until past the last day LinkedIn's dates reach, yesterday or the day before, reads as that day. Alone, it starts the window about a year back, as far as LinkedIn's dates reach, so an ad that last ran before then is left out.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 24,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 24,
              "maximum": 24,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "advertiser": {
                            "avatar_url": "https://media.licdn.com/dms/image/v2/D560BAQEIaRrwk0U4rQ/company-logo_100_100/B56ZzvpVifGgAQ-/0/1773547118379?e=1795651200&v=beta&t=vVXt4dCbakReQkbQPJrw_QSQBARm52OsR5i2FLsj7IY",
                            "display_name": "Islands Business partners",
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "approximate_fields": [
                            "creatives[].body"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": "📢 𝐖𝐄’𝐑𝐄 𝐇𝐈𝐑𝐈𝐍𝐆: 𝐏𝐀𝐑𝐓-𝐓𝐈𝐌𝐄 𝐂𝐎𝐌𝐌𝐔𝐍𝐈𝐂𝐀𝐓𝐈𝐎𝐍𝐒 𝐄𝐍𝐀𝐁𝐋𝐄𝐑 The Pacific Feminist Fund (PFF…",
                              "cta_text": null,
                              "link_description": null,
                              "link_url": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": null,
                                  "height": null,
                                  "thumbnail_url": null,
                                  "type": "image",
                                  "url": "https://media.licdn.com/dms/image/v2/D5622AQGoYNnaxFJk9w/feedshare-image-high-res/B56aGedhCvGgAU-/0/1793659900333?e=2147483647&v=beta&t=tIdGsaeRuhSzKZL_4B0AXHa4AlPH0G_pueTxmtkg3zw",
                                  "width": null
                                }
                              ],
                              "title": null
                            }
                          ],
                          "first_shown_at": null,
                          "id": "1624871424",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": null,
                          "paid_by": null,
                          "platform": "linkedin",
                          "platform_specific": {
                            "linkedin": {
                              "company": null,
                              "creative_type": "SPONSORED_STATUS_UPDATE",
                              "document": null,
                              "event": null,
                              "format": "Single Image Ad",
                              "impressions_by_country": [],
                              "is_deleted": false,
                              "job": null,
                              "message": null,
                              "newsletter": null,
                              "poster": {
                                "avatar_url": "https://media.licdn.com/dms/image/v2/D560BAQEIaRrwk0U4rQ/company-logo_100_100/B56ZzvpVifGgAQ-/0/1773547118379?e=1795651200&v=beta&t=vVXt4dCbakReQkbQPJrw_QSQBARm52OsR5i2FLsj7IY",
                                "display_name": "Islands Business partners",
                                "id": null,
                                "is_verified": null,
                                "url": null,
                                "username": null
                              },
                              "poster_title": null,
                              "targeting": null
                            }
                          },
                          "publisher_platforms": [],
                          "reach": null,
                          "spend": null,
                          "type": "image",
                          "unknown_fields": [
                            "country_codes",
                            "languages",
                            "platform_specific.linkedin.impressions_by_country"
                          ],
                          "url": "https://www.linkedin.com/ad-library/detail/1624871424"
                        },
                        {
                          "advertiser": {
                            "avatar_url": "https://media.licdn.com/dms/image/v2/D4D0BAQEoATmtfABDag/company-logo_100_100/B4DaGIY1kPKEAM-/0/1793289574883/useburhan_logo?e=1795651200&v=beta&t=Ki3wxQ09lYYE4V7ydEMx_SAoxn-u-wbIsLMqxvskQ2M",
                            "display_name": "Burhan",
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "approximate_fields": [
                            "creatives[].body"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": "Is it safe to release? Most teams answer with a feeling. Burhan answers with proof. It walks each journey of your web o…",
                              "cta_text": null,
                              "link_description": null,
                              "link_url": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": null,
                                  "height": null,
                                  "thumbnail_url": "https://media.licdn.com/dms/image/v2/D4E10AQFNh6bkCLYxvA/videocover-high/B4EaGee1l_G8BI-/0/1793660247890?e=2147483647&v=beta&t=IHiqwgf_DYoUES10JT3_-iWDgCZEcymMvTFhz3PpUdA",
                                  "type": "video",
                                  "url": null,
                                  "width": null
                                }
                              ],
                              "title": "Release with proof"
                            }
                          ],
                          "first_shown_at": null,
                          "id": "1624744724",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": null,
                          "paid_by": null,
                          "platform": "linkedin",
                          "platform_specific": {
                            "linkedin": {
                              "company": null,
                              "creative_type": "SPONSORED_VIDEO",
                              "document": null,
                              "event": null,
                              "format": "Video Ad",
                              "impressions_by_country": [],
                              "is_deleted": false,
                              "job": null,
                              "message": null,
                              "newsletter": null,
                              "poster": {
                                "avatar_url": "https://media.licdn.com/dms/image/v2/D4D0BAQEoATmtfABDag/company-logo_100_100/B4DaGIY1kPKEAM-/0/1793289574883/useburhan_logo?e=1795651200&v=beta&t=Ki3wxQ09lYYE4V7ydEMx_SAoxn-u-wbIsLMqxvskQ2M",
                                "display_name": "Burhan",
                                "id": null,
                                "is_verified": null,
                                "url": null,
                                "username": null
                              },
                              "poster_title": null,
                              "targeting": null
                            }
                          },
                          "publisher_platforms": [],
                          "reach": null,
                          "spend": null,
                          "type": "video",
                          "unknown_fields": [
                            "country_codes",
                            "languages",
                            "platform_specific.linkedin.impressions_by_country"
                          ],
                          "url": "https://www.linkedin.com/ad-library/detail/1624744724"
                        },
                        {
                          "advertiser": {
                            "avatar_url": "https://media.licdn.com/dms/image/v2/D4E03AQEyCndQwhrggQ/profile-displayphoto-scale_100_100/B4EaBOhxICIoAY-/0/1788023870982?e=1795651200&v=beta&t=EEOax4ztSgJPzwXaetBUkgEL1PwhCJtCL8aPWHIbaH8",
                            "display_name": "Abdulrahman Mohamed",
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "approximate_fields": [
                            "creatives[].body"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": "🌍 READY FOR MY NEXT INTERNATIONAL HOSPITALITY CHAPTER Exceptional hospitality is not just about service — it is about …",
                              "cta_text": null,
                              "link_description": null,
                              "link_url": null,
                              "media": [],
                              "title": null
                            }
                          ],
                          "first_shown_at": null,
                          "id": "1624659644",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": null,
                          "paid_by": null,
                          "platform": "linkedin",
                          "platform_specific": {
                            "linkedin": {
                              "company": null,
                              "creative_type": "SPONSORED_STATUS_UPDATE",
                              "document": null,
                              "event": null,
                              "format": "Single Image Ad",
                              "impressions_by_country": [],
                              "is_deleted": false,
                              "job": null,
                              "message": null,
                              "newsletter": null,
                              "poster": {
                                "avatar_url": "https://media.licdn.com/dms/image/v2/D4E03AQEyCndQwhrggQ/profile-displayphoto-scale_100_100/B4EaBOhxICIoAY-/0/1788023870982?e=1795651200&v=beta&t=EEOax4ztSgJPzwXaetBUkgEL1PwhCJtCL8aPWHIbaH8",
                                "display_name": "Abdulrahman Mohamed",
                                "id": null,
                                "is_verified": null,
                                "url": null,
                                "username": null
                              },
                              "poster_title": "Head Waiter | Luxury Hospitality & Fine Dining | VIP Guest Experience | F&B Professional | Open to International Opportunities",
                              "targeting": null
                            }
                          },
                          "publisher_platforms": [],
                          "reach": null,
                          "spend": null,
                          "type": "image",
                          "unknown_fields": [
                            "country_codes",
                            "languages",
                            "platform_specific.linkedin.impressions_by_country"
                          ],
                          "url": "https://www.linkedin.com/ad-library/detail/1624659644"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "linkedin",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1102,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/LinkedinSearch_adsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Ads by keyword, advertiser or payer",
        "tags": [
          "LinkedIn Ad Library"
        ],
        "x-socialtap-endpoint": "linkedin.search_ads",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "most recently started first",
          "orders": {
            "newest": "most recently started first",
            "oldest": "earliest started first"
          },
          "page_max": 24,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "ad",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/linkedin/search_posts": {
      "get": {
        "description": "Returns public LinkedIn posts for a keyword or hashtag, found through a web search, with each post's link, exact publish time and author. Each result also has the search index's excerpt of the text and its comment count. Add fill=true to get each post's full, live record in the same response: whole text, media, exact reaction and comment counts and top comments.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/linkedin/search_posts/ (Markdown: https://socialtap.dev/docs/reference/linkedin/search_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/linkedin/search_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/linkedin/search_posts/"
        },
        "operationId": "linkedin.search_posts.list",
        "parameters": [
          {
            "description": "Words to find LinkedIn posts by, as a web search reads them: a topic, a phrase, a name or a hashtag (supply chain resilience, \"remote work\" burnout, #sustainability). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and intitle:, inurl: and intext: count as plain words.",
            "example": "supply chain resilience",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find LinkedIn posts by, as a web search reads them: a topic, a phrase, a name or a hashtag (supply chain resilience, \"remote work\" burnout, #sustainability). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and intitle:, inurl: and intext: count as plain words.",
              "examples": [
                "supply chain resilience"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "post.author.display_name",
                            "post.text"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.linkedin.com/posts/boston-consulting-group_leading-through-resilience-supply-chain-activity-7038522324806946816-WIrq",
                          "place": null,
                          "platform": "linkedin",
                          "platform_specific": {
                            "linkedin": {
                              "company": null,
                              "connection_count": null,
                              "headline": null,
                              "kind": null,
                              "location": null,
                              "school": null,
                              "tagline": null
                            }
                          },
                          "position": 0,
                          "post": {
                            "author": {
                              "avatar_url": null,
                              "display_name": "Boston Consulting Group (BCG)",
                              "id": null,
                              "is_verified": null,
                              "url": null,
                              "username": "boston-consulting-group"
                            },
                            "id": null,
                            "metrics": {
                              "comment_count": null,
                              "like_count": null,
                              "quote_count": null,
                              "repost_count": null,
                              "save_count": null,
                              "share_count": null,
                              "view_count": null
                            },
                            "published_at": "2023-03-06T14:54:51Z",
                            "text": "To mitigate the impact of supply chain disruptions, companies can implement several solutions, such as: Diversification: Companies can diversify their suppliers and manufacturing locations to reduce the dependency on a single source. Risk Assessment: Conducting regular risk asses…",
                            "thumbnail_url": null,
                            "title": null,
                            "url": "https://www.linkedin.com/feed/update/urn:li:activity:7038522324806946816"
                          },
                          "profile": null,
                          "snippet": "To mitigate the impact of supply chain disruptions, companies can implement several solutions, such as: Diversification: Companies can diversify their suppliers and manufacturing locations to reduce the dependency on a single source. Risk Assessment: Conducting regular risk asses…",
                          "sound": null,
                          "title": "Boston Consulting Group (BCG) on LinkedIn: Leading Through ...",
                          "type": "post",
                          "unknown_fields": [],
                          "url": "https://www.linkedin.com/feed/update/urn:li:activity:7038522324806946816"
                        },
                        {
                          "approximate_fields": [
                            "post.author.display_name",
                            "post.text"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.linkedin.com/posts/supplychainoptimization_the-resilience-myth-fatal-flaws-in-the-push-activity-6958252361312059392-eHg8",
                          "place": null,
                          "platform": "linkedin",
                          "platform_specific": {
                            "linkedin": {
                              "company": null,
                              "connection_count": null,
                              "headline": null,
                              "kind": null,
                              "location": null,
                              "school": null,
                              "tagline": null
                            }
                          },
                          "position": 1,
                          "post": {
                            "author": {
                              "avatar_url": null,
                              "display_name": "Brian Laung Aoaeh, CFA",
                              "id": null,
                              "is_verified": null,
                              "url": null,
                              "username": "supplychainoptimization"
                            },
                            "id": null,
                            "metrics": {
                              "comment_count": null,
                              "like_count": null,
                              "quote_count": null,
                              "repost_count": null,
                              "save_count": null,
                              "share_count": null,
                              "view_count": null
                            },
                            "published_at": "2022-07-28T02:50:41Z",
                            "text": "“So-called supply chain resilience has become a central aim of policy. But such resilience is a myth.” I couldn’t agree more with Cheng Ting-Fang and ...",
                            "thumbnail_url": null,
                            "title": null,
                            "url": "https://www.linkedin.com/feed/update/urn:li:activity:6958252361312059392"
                          },
                          "profile": null,
                          "snippet": "“So-called supply chain resilience has become a central aim of policy. But such resilience is a myth.” I couldn’t agree more with Cheng Ting-Fang and ...",
                          "sound": null,
                          "title": "Brian Laung Aoaeh, CFA on LinkedIn: The resilience myth: Fatal ...",
                          "type": "post",
                          "unknown_fields": [],
                          "url": "https://www.linkedin.com/feed/update/urn:li:activity:6958252361312059392"
                        },
                        {
                          "approximate_fields": [
                            "post.author.display_name",
                            "post.text"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.linkedin.com/posts/kearney_three-keys-to-a-regenerative-supply-chain-activity-7140106302587924480-a-Zb",
                          "place": null,
                          "platform": "linkedin",
                          "platform_specific": {
                            "linkedin": {
                              "company": null,
                              "connection_count": null,
                              "headline": null,
                              "kind": null,
                              "location": null,
                              "school": null,
                              "tagline": null
                            }
                          },
                          "position": 2,
                          "post": {
                            "author": {
                              "avatar_url": null,
                              "display_name": "Kearney",
                              "id": null,
                              "is_verified": null,
                              "url": null,
                              "username": "kearney"
                            },
                            "id": null,
                            "metrics": {
                              "comment_count": null,
                              "like_count": null,
                              "quote_count": null,
                              "repost_count": null,
                              "save_count": null,
                              "share_count": null,
                              "view_count": null
                            },
                            "published_at": "2023-12-11T22:33:19Z",
                            "text": "Diversification, regionalization, and a renewed focus on cost efficiency are key strategies. 💡 Learn how the industry is gearing up for the 2023 holiday season and embracing sustainability and digitalization. 🌿 Dive into the full report to uncover actionable recommendations for b…",
                            "thumbnail_url": null,
                            "title": null,
                            "url": "https://www.linkedin.com/feed/update/urn:li:activity:7140106302587924480"
                          },
                          "profile": null,
                          "snippet": "Diversification, regionalization, and a renewed focus on cost efficiency are key strategies. 💡 Learn how the industry is gearing up for the 2023 holiday season and embracing sustainability and digitalization. 🌿 Dive into the full report to uncover actionable recommendations for b…",
                          "sound": null,
                          "title": "Kearney on LinkedIn: Three keys to a regenerative supply chain ...",
                          "type": "post",
                          "unknown_fields": [],
                          "url": "https://www.linkedin.com/feed/update/urn:li:activity:7140106302587924480"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "linkedin",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1163,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/LinkedinSearch_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Public posts by keyword or hashtag",
        "tags": [
          "LinkedIn"
        ],
        "x-socialtap-endpoint": "linkedin.search_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/linkedin/search_profiles": {
      "get": {
        "description": "Returns the LinkedIn companies, schools, showcase Pages and members a public web search finds for your words, or only one kind with account_type. Each result has its link and name, plus what the search index shows: a Page's tagline, about text and followers, or a member's headline, location, employer, school and connections. Add fill=true to get the live LinkedIn profile of each account LinkedIn shows logged out, in the same response.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/linkedin/search_profiles/ (Markdown: https://socialtap.dev/docs/reference/linkedin/search_profiles/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/linkedin/search_profiles/index.md)",
          "url": "https://socialtap.dev/docs/reference/linkedin/search_profiles/"
        },
        "operationId": "linkedin.search_profiles.list",
        "parameters": [
          {
            "description": "Words to find LinkedIn accounts by, as a web search reads them: a company's or a person's name, an industry and a place, a job title and an employer (stripe, coffee roaster seattle, \"bill gates\", software engineer stripe). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and intitle:, inurl: and intext: count as plain words.",
            "example": "coffee roaster",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find LinkedIn accounts by, as a web search reads them: a company's or a person's name, an industry and a place, a job title and an employer (stripe, coffee roaster seattle, \"bill gates\", software engineer stripe). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and intitle:, inurl: and intext: count as plain words.",
              "examples": [
                "coffee roaster"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Only accounts of this kind: company (a company's Page), school (a school's Page), showcase (a company's page for one brand or product) or member (a person). Every kind when omitted, which finds fewer of each: use it when you know what you are looking for.",
            "example": "company",
            "in": "query",
            "name": "account_type",
            "schema": {
              "description": "Only accounts of this kind: company (a company's Page), school (a school's Page), showcase (a company's page for one brand or product) or member (a person). Every kind when omitted, which finds fewer of each: use it when you know what you are looking for.",
              "enum": [
                "company",
                "school",
                "showcase",
                "member"
              ],
              "examples": [
                "company"
              ],
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "profile.bio",
                            "profile.display_name",
                            "profile.metrics.follower_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.linkedin.com/company/red-rooster-coffee-roaster",
                          "place": null,
                          "platform": "linkedin",
                          "platform_specific": {
                            "linkedin": {
                              "company": null,
                              "connection_count": null,
                              "headline": null,
                              "kind": "company",
                              "location": null,
                              "school": null,
                              "tagline": null
                            }
                          },
                          "position": 0,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "Floyd's first fair trade, organic coffee roaster, located in Floyd, VA. Whole bean coffee from around the world, artisan roasted and shipped to your doorstep.",
                            "display_name": "Red Rooster Coffee Roaster",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": 368,
                              "following_count": null,
                              "post_count": null,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://www.linkedin.com/company/red-rooster-coffee-roaster",
                            "username": "red-rooster-coffee-roaster"
                          },
                          "snippet": "Red Rooster Coffee Roaster | 368 followers on LinkedIn. Floyd's first fair trade, organic coffee roaster, located in Floyd, VA. Whole bean coffee from around the world, artisan roasted and shipped to your doorstep.",
                          "sound": null,
                          "title": "Red Rooster Coffee Roaster | LinkedIn",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://www.linkedin.com/company/red-rooster-coffee-roaster"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.linkedin.tagline",
                            "profile.bio",
                            "profile.display_name"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.linkedin.com/company/alabaster-coffee-roaster-&-tea-company",
                          "place": null,
                          "platform": "linkedin",
                          "platform_specific": {
                            "linkedin": {
                              "company": null,
                              "connection_count": null,
                              "headline": null,
                              "kind": "company",
                              "location": null,
                              "school": null,
                              "tagline": "Cultivating community though the elevation of coffee culture."
                            }
                          },
                          "position": 1,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "Alabaster Coffee is a nationally award winning coffee bar & roasterie located in Williamsport, PA.",
                            "display_name": "Alabaster Coffee Roaster & Tea Company",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": 319,
                              "following_count": null,
                              "post_count": null,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://www.linkedin.com/company/alabaster-coffee-roaster-&-tea-company",
                            "username": "alabaster-coffee-roaster-&-tea-company"
                          },
                          "snippet": "Alabaster Coffee Roaster & Tea Company | 319 followers on LinkedIn. Cultivating community though the elevation of coffee culture. | Alabaster Coffee is a nationally award winning coffee bar & roasterie located in Williamsport, PA.",
                          "sound": null,
                          "title": "Alabaster Coffee Roaster & Tea Company | LinkedIn",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://www.linkedin.com/company/alabaster-coffee-roaster-&-tea-company"
                        },
                        {
                          "approximate_fields": [
                            "profile.display_name"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.linkedin.com/company/mozart's-coffee-roasters",
                          "place": null,
                          "platform": "linkedin",
                          "platform_specific": {
                            "linkedin": {
                              "company": null,
                              "connection_count": null,
                              "headline": null,
                              "kind": "company",
                              "location": null,
                              "school": null,
                              "tagline": null
                            }
                          },
                          "position": 2,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": null,
                            "display_name": "Mozart's Coffee Roasters",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": null,
                              "following_count": null,
                              "post_count": null,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://www.linkedin.com/company/mozart%27s-coffee-roasters",
                            "username": "mozart's-coffee-roasters"
                          },
                          "snippet": "Operating a scratch bakery on-premise and producing European style hand-made, hand-cut freshly baked cakes, bars, cookies, and savory items such as sandwiches, tacos, and empanadas much in the style of a Grand Cafe is our speciality. Our coffees are ethically sourced from around …",
                          "sound": null,
                          "title": "Mozart's Coffee Roasters | LinkedIn",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://www.linkedin.com/company/mozart%27s-coffee-roasters"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "linkedin",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1231,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/LinkedinSearch_profilesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Companies, schools and people by keyword",
        "tags": [
          "LinkedIn"
        ],
        "x-socialtap-endpoint": "linkedin.search_profiles",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/linkme/profile": {
      "get": {
        "description": "Returns a public Linkme profile with its total followers, each social account's handle and followers, every link and its contact details. Contact details are the emails, phone numbers and street addresses the page lists. Each link has its title, description, thumbnail and section, and a music link its destination on each streaming service. The profile adds the name, bio, picture, logo, banner, verified badge, and when it was created and last changed. Send the page's name or link.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\nIn Linkme's words: `metrics.follower_count` is total followers.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/linkme/profile/ (Markdown: https://socialtap.dev/docs/reference/linkme/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/linkme/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/linkme/profile/"
        },
        "operationId": "linkme.profile.get",
        "parameters": [
          {
            "description": "The Linkme page: its name (papisteak, with or without the @) or its link (https://link.me/papisteak).",
            "example": "papisteak",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Linkme page: its name (papisteak, with or without the @) or its link (https://link.me/papisteak).",
              "examples": [
                "papisteak"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "platform_specific.linkme.profile_visit_count"
                        ],
                        "avatar_url": "https://media.link.me/images/user-profile/2123271/tmp-565-1766183620379.png",
                        "banner_url": null,
                        "bio": "Iconic high-energy Steakhouse",
                        "category": null,
                        "country_code": null,
                        "created_at": "2025-12-19T19:47:40Z",
                        "display_name": "Papi Steak",
                        "external_links": [
                          {
                            "title": "Instagram",
                            "url": "https://www.instagram.com/papisteak"
                          },
                          {
                            "title": "Facebook",
                            "url": "https://www.facebook.com/papisteakmiami/"
                          },
                          {
                            "title": "Threads",
                            "url": "https://www.threads.net/@papisteak?igshid=NTc4MTIwNjQ2YQ=="
                          }
                        ],
                        "id": "2123271",
                        "is_private": false,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 239913,
                          "following_count": null,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "linkme",
                        "platform_specific": {
                          "linkme": {
                            "emails": [],
                            "featured_links": [
                              {
                                "description": null,
                                "group": null,
                                "id": "1688371",
                                "image_url": "https://media.link.me/images/external-links/2123271/1793642723656.png",
                                "is_adult": false,
                                "platform": "link",
                                "platforms": [],
                                "section": null,
                                "title": "Doordash",
                                "url": "https://order.online/business/24734529/store/51360639"
                              },
                              {
                                "description": null,
                                "group": null,
                                "id": "686462",
                                "image_url": "https://media.link.me/images/external-links/2123271/1766177538178.jpeg",
                                "is_adult": false,
                                "platform": "link",
                                "platforms": [],
                                "section": null,
                                "title": "Website",
                                "url": "https://papisteak.com/"
                              },
                              {
                                "description": null,
                                "group": null,
                                "id": "686481",
                                "image_url": "https://media.link.me/images/external-links/2123271/1766177573005.jpeg",
                                "is_adult": false,
                                "platform": "link",
                                "platforms": [],
                                "section": "PAPI STEAK MIAMI BEACH",
                                "title": "Menu",
                                "url": "https://papisteak.com/miami/menu/"
                              }
                            ],
                            "is_adult": false,
                            "link_count": 16,
                            "linkme_connection_count": 2,
                            "locations": [],
                            "logo_url": "https://media.link.me/images/logo-image/2123271/tmp-2241-1778613564542.png",
                            "network_follower_count": 239911,
                            "phones": [],
                            "profile_visit_count": 15400,
                            "social_links": [
                              {
                                "follower_count": 194575,
                                "handle": "papisteak",
                                "is_adult": false,
                                "platform": "Instagram",
                                "url": "https://www.instagram.com/papisteak"
                              },
                              {
                                "follower_count": 7900,
                                "handle": "papisteakmiami",
                                "is_adult": false,
                                "platform": "Facebook",
                                "url": "https://www.facebook.com/papisteakmiami/"
                              },
                              {
                                "follower_count": 37436,
                                "handle": "papisteak",
                                "is_adult": false,
                                "platform": "Threads",
                                "url": "https://www.threads.net/@papisteak?igshid=NTc4MTIwNjQ2YQ=="
                              }
                            ],
                            "updated_at": "2026-08-28T22:13:02Z"
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://link.me/papisteak",
                        "username": "papisteak"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "linkme",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 281,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "2123271",
                          "url": "https://link.me/papisteak"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/LinkmeProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Total followers, social handles and every link",
        "tags": [
          "Linkme"
        ],
        "x-socialtap-endpoint": "linkme.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/linktree/profile": {
      "get": {
        "description": "Returns every link on a public Linktree page, in page order, with its social icons, bio and contact email, from a username or link. Each link has its label, destination, type, thumbnail and group. The profile adds the page's ID, title, avatar, banner, verified badge, country, category and join date.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/linktree/profile/ (Markdown: https://socialtap.dev/docs/reference/linktree/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/linktree/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/linktree/profile/"
        },
        "operationId": "linktree.profile.get",
        "parameters": [
          {
            "description": "The Linktree page: a username with or without the @, or its link (linktr.ee/<username>, in any case, with or without a query).",
            "example": "SbuxIDOfficialStores",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Linktree page: a username with or without the @, or its link (linktr.ee/<username>, in any case, with or without a query).",
              "examples": [
                "selenagomez"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://ugc.production.linktr.ee/DQQCWwlZT7qHu3orFoIg_5DNrZjnwDtbJHpmu",
                        "banner_url": null,
                        "bio": null,
                        "category": "restaurant",
                        "country_code": "ID",
                        "created_at": "2021-03-02T05:07:54Z",
                        "display_name": "Starbucks Indonesia",
                        "external_links": [
                          {
                            "title": "Find The Nearest Starbucks",
                            "url": "https://www.starbucks.co.id/store-locator"
                          },
                          {
                            "title": "Starbucks Delivers: GoFood Order",
                            "url": "https://gofood.link/a/GN1xGkj"
                          },
                          {
                            "title": "Download aplikasi Grab untuk transportasi dan pengantaran makanan | Grab ID",
                            "url": "https://tinyurl.com/GrabStarbucksDelivery"
                          }
                        ],
                        "id": "13053310",
                        "is_private": false,
                        "is_verified": false,
                        "location": null,
                        "metrics": {
                          "follower_count": null,
                          "following_count": null,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "linktree",
                        "platform_specific": {
                          "linktree": {
                            "badges": [],
                            "content_warning": null,
                            "email": "customer.care@Starbucks.co.id",
                            "is_sensitive": false,
                            "link_platforms": [
                              "Instagram"
                            ],
                            "links": [
                              {
                                "gates": [],
                                "group_id": null,
                                "id": "301194825",
                                "position": 5,
                                "thumbnail_url": null,
                                "title": "Find The Nearest Starbucks",
                                "type": "CLASSIC",
                                "url": "https://www.starbucks.co.id/store-locator"
                              },
                              {
                                "gates": [],
                                "group_id": null,
                                "id": "217384595",
                                "position": 6,
                                "thumbnail_url": null,
                                "title": "Starbucks Delivers: GoFood Order",
                                "type": "CLASSIC",
                                "url": "https://gofood.link/a/GN1xGkj"
                              },
                              {
                                "gates": [],
                                "group_id": null,
                                "id": "87194845",
                                "position": 7,
                                "thumbnail_url": "https://ugc.production.linktr.ee/4acb18e0-8e2e-44f1-b449-782478e9bbea_download-app-screen-ID.png",
                                "title": "Download aplikasi Grab untuk transportasi dan pengantaran makanan | Grab ID",
                                "type": "CLASSIC",
                                "url": "https://tinyurl.com/GrabStarbucksDelivery"
                              }
                            ],
                            "social_links": [
                              {
                                "platform": "instagram",
                                "url": "https://www.instagram.com/starbucksindonesia/"
                              },
                              {
                                "platform": "email_address",
                                "url": "mailto:customer.care@Starbucks.co.id"
                              }
                            ],
                            "timezone": "Asia/Jakarta",
                            "updated_at": "2026-10-06T08:09:22Z",
                            "verticals": [
                              "brand",
                              "creative",
                              "ecommerce"
                            ]
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://linktr.ee/SbuxIDOfficialStores",
                        "username": "SbuxIDOfficialStores"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "linktree",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1285,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "13053310",
                          "url": "https://linktr.ee/SbuxIDOfficialStores"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/LinktreeProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Every link on a page, with social icons and email",
        "tags": [
          "Linktree"
        ],
        "x-socialtap-endpoint": "linktree.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/members": {
      "get": {
        "description": "Everyone on the account with their roles, the owner first. Free.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "members.list",
        "parameters": [
          {
            "description": "Members per page (default and maximum 100).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "email": {
                            "description": "Their verified email address.",
                            "type": "string"
                          },
                          "is_you": {
                            "description": "Whether this is the signed-in person.",
                            "type": "boolean"
                          },
                          "joined_at": {
                            "description": "When they joined the account, RFC 3339 UTC.",
                            "format": "date-time",
                            "type": "string"
                          },
                          "object": {
                            "description": "Always member.",
                            "enum": [
                              "member"
                            ],
                            "type": "string"
                          },
                          "role": {
                            "description": "owner: everything, including deleting the account and handing it to someone else (exactly one). admin: billing, keys, webhooks, settings and people, never the owner. member: reads the account and uses the playground with a key it is given; changes nothing.",
                            "enum": [
                              "owner",
                              "admin",
                              "member"
                            ],
                            "type": "string"
                          },
                          "user_id": {
                            "description": "The person's ID: change their role or remove them with it.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "object",
                          "user_id",
                          "email",
                          "role",
                          "joined_at",
                          "is_you"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List the account's people",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "List the account's people",
        "tags": [
          "Team"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/members/{user_id}": {
      "delete": {
        "description": "Takes the person off the account at once. Keys stay: they are the account's. The answer lists the API keys and webhook endpoints the person created that still work, to review and revoke. The owner can't be removed. Free.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "members.remove",
        "parameters": [
          {
            "description": "The person's ID (GET /v1/members).",
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "api_keys": {
                          "description": "The API keys they created or last rotated, directly or through a key of theirs, that aren't revoked. They keep working until revoked: DELETE /v1/api_keys/{id}.",
                          "items": {
                            "properties": {
                              "created_at": {
                                "description": "When the key was created, RFC 3339 UTC.",
                                "format": "date-time",
                                "type": "string"
                              },
                              "created_by_key": {
                                "description": "The API key (key_…) that last created this key, gave it the admin scope or rotated it: revoking that key also revokes this one if this one has admin. Null when none did, or a person has rotated it in the dashboard since.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "created_by_user": {
                                "description": "The person (GET /v1/members user_id) who created this key in the dashboard, or whose key created it. They may have left the account since. Null when no person did (an operator, or a key from before this was recorded).",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "dashboard": {
                                "description": "true for the account's built-in dashboard key: the dashboard's playground runs as it (so its requests are logged, counted and billed like any key's). Nobody holds its secret, so it works only from the signed-in dashboard. Only its spend_limit can be changed (to cap what the playground spends live); renaming, rescoping, restricting, rotating or revoking it is forbidden (details.reason dashboard_key). It is made on first use and revoked with the account.",
                                "type": "boolean"
                              },
                              "expires_at": {
                                "description": "When the key stops working, RFC 3339 UTC; null when it never expires.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "id": {
                                "description": "Key ID (key_…): manage the key with it. It is not the secret.",
                                "type": "string"
                              },
                              "ip_allowlist": {
                                "description": "IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; [] = any.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "last_used_at": {
                                "description": "About when the key was last used (updated at most hourly); null when never.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "name": {
                                "description": "Your label for the key.",
                                "type": "string"
                              },
                              "object": {
                                "description": "Always api_key.",
                                "enum": [
                                  "api_key"
                                ],
                                "type": "string"
                              },
                              "prefix": {
                                "description": "The secret's first characters, to recognize it.",
                                "type": "string"
                              },
                              "previous_secret_expires_at": {
                                "description": "Until then the secret this key had before its last rotation works too (rotate_secret), RFC 3339 UTC; null when none does.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "revoked_at": {
                                "description": "When the key was revoked; null while it is not.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "scopes": {
                                "description": "What the key may call: endpoints (data endpoints), jobs (create, read and cancel jobs; includes jobs:read), jobs:read (read jobs and their results), account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).",
                                "items": {
                                  "enum": [
                                    "endpoints",
                                    "jobs",
                                    "jobs:read",
                                    "account:read",
                                    "admin"
                                  ],
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "spend_limit": {
                                "description": "The key's spend limit and what it used this interval; null when the key has none.",
                                "properties": {
                                  "amount": {
                                    "description": "Most credits the key may spend per interval.",
                                    "type": "integer"
                                  },
                                  "interval": {
                                    "description": "Calendar day or month, UTC.",
                                    "enum": [
                                      "day",
                                      "month"
                                    ],
                                    "type": "string"
                                  },
                                  "resets_at": {
                                    "description": "Start of the next interval, RFC 3339 UTC.",
                                    "format": "date-time",
                                    "type": "string"
                                  },
                                  "used": {
                                    "description": "Credits the key spent this interval, plus what its requests in flight hold.",
                                    "type": "integer"
                                  }
                                },
                                "required": [
                                  "amount",
                                  "interval",
                                  "used",
                                  "resets_at"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              },
                              "status": {
                                "description": "pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.",
                                "enum": [
                                  "active",
                                  "pending",
                                  "expired",
                                  "revoked"
                                ],
                                "type": "string"
                              }
                            },
                            "required": [
                              "object",
                              "id",
                              "name",
                              "status",
                              "prefix",
                              "scopes",
                              "spend_limit",
                              "expires_at",
                              "ip_allowlist",
                              "created_at",
                              "last_used_at",
                              "revoked_at",
                              "dashboard",
                              "previous_secret_expires_at",
                              "created_by_key",
                              "created_by_user"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "deleted": {
                          "description": "Always true.",
                          "type": "boolean"
                        },
                        "id": {
                          "type": "string"
                        },
                        "object": {
                          "description": "The deleted object's type (webhook_endpoint).",
                          "type": "string"
                        },
                        "unattributed_api_keys": {
                          "description": "How many other working keys on the account no person is recorded for (older than the record): they could be this person's too, so review them.",
                          "type": "integer"
                        },
                        "webhook_endpoints": {
                          "description": "The live webhook endpoints they created or last pointed somewhere. They keep receiving events until deleted: DELETE /v1/webhook_endpoints/{id}.",
                          "items": {
                            "properties": {
                              "created_at": {
                                "format": "date-time",
                                "type": "string"
                              },
                              "created_by_user": {
                                "description": "The person (GET /v1/members user_id) who created this endpoint in the dashboard, or whose API key created it. They may have left the account since. Null when no person did, or it is from before this was recorded.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "description": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "disabled_reason": {
                                "description": "Why it is disabled: gone (it answered 410), failing (deliveries failed for 5 days), user. Null while enabled.",
                                "enum": [
                                  "gone",
                                  "failing",
                                  "user"
                                ],
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "events": {
                                "description": "Event types it receives: types, prefix wildcards (job.*) or * for all.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "id": {
                                "description": "we_…",
                                "type": "string"
                              },
                              "object": {
                                "description": "Always webhook_endpoint.",
                                "enum": [
                                  "webhook_endpoint"
                                ],
                                "type": "string"
                              },
                              "previous_secret_expires_at": {
                                "description": "Until then the previous secret signs too; null when none.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "secret": {
                                "description": "The signing secret (whsec_…): only in the create and rotate_secret answers. Store it.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "status": {
                                "enum": [
                                  "enabled",
                                  "disabled"
                                ],
                                "type": "string"
                              },
                              "updated_at": {
                                "format": "date-time",
                                "type": "string"
                              },
                              "url": {
                                "description": "https URL deliveries are POSTed to. A key an agent collected from an approval reads only its host: https://host/.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "object",
                              "id",
                              "url",
                              "events",
                              "description",
                              "status",
                              "disabled_reason",
                              "previous_secret_expires_at",
                              "created_at",
                              "updated_at",
                              "created_by_user"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "deleted",
                        "api_keys",
                        "webhook_endpoints",
                        "unattributed_api_keys"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Remove someone from the account",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Remove someone from the account",
        "tags": [
          "Team"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "patch": {
        "description": "Makes someone an admin or a member (yourself included). The owner's role changes only by a handover. Free.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "members.update",
        "parameters": [
          {
            "description": "The person's ID (GET /v1/members).",
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "role": {
                    "description": "Their new role. The owner's role never changes here: the owner hands the account over with POST /v1/account/transfer.",
                    "enum": [
                      "admin",
                      "member"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "role"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "email": {
                          "description": "Their verified email address.",
                          "type": "string"
                        },
                        "is_you": {
                          "description": "Whether this is the signed-in person.",
                          "type": "boolean"
                        },
                        "joined_at": {
                          "description": "When they joined the account, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always member.",
                          "enum": [
                            "member"
                          ],
                          "type": "string"
                        },
                        "role": {
                          "description": "owner: everything, including deleting the account and handing it to someone else (exactly one). admin: billing, keys, webhooks, settings and people, never the owner. member: reads the account and uses the playground with a key it is given; changes nothing.",
                          "enum": [
                            "owner",
                            "admin",
                            "member"
                          ],
                          "type": "string"
                        },
                        "user_id": {
                          "description": "The person's ID: change their role or remove them with it.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "user_id",
                        "email",
                        "role",
                        "joined_at",
                        "is_you"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Change someone's role",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Change someone's role",
        "tags": [
          "Team"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/notification_preferences": {
      "get": {
        "description": "Per category: email and dashboard on or off (default on). Security mail is always sent. Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "notification_preferences.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "categories": {
                          "description": "Every notification category, in display order. Security email is in none: it is always sent.",
                          "items": {
                            "properties": {
                              "category": {
                                "description": "The notification category.",
                                "enum": [
                                  "credits",
                                  "spend_limits",
                                  "jobs",
                                  "api_keys",
                                  "webhooks"
                                ],
                                "type": "string"
                              },
                              "email": {
                                "description": "Whether the owner is emailed (default on); null when the category sends no email.",
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              },
                              "in_app": {
                                "description": "Whether the dashboard shows it (default on). Webhooks always get every event.",
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "category",
                              "email",
                              "in_app"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "object": {
                          "description": "Always notification_preferences.",
                          "enum": [
                            "notification_preferences"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "categories"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get notification preferences",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Get notification preferences",
        "tags": [
          "Notifications"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "patch": {
        "description": "Turns a category's email or dashboard notifications on or off; the rest keep theirs. Only the dashboard turns off a category marked `session_mute` (API keys): an API key that tries gets forbidden, reason session_only. Free.\n\n**Auth:** an API key with the `admin` scope, or the dashboard session.",
        "operationId": "notification_preferences.update",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "categories": {
                    "description": "The categories to change, each at most once.",
                    "items": {
                      "properties": {
                        "category": {
                          "description": "The notification category.",
                          "enum": [
                            "credits",
                            "spend_limits",
                            "jobs",
                            "api_keys",
                            "webhooks"
                          ],
                          "type": "string"
                        },
                        "email": {
                          "description": "Email on or off; only for a category that sends email (its email is not null).",
                          "type": [
                            "boolean",
                            "null"
                          ]
                        },
                        "in_app": {
                          "description": "Shown in the dashboard's notifications, or not.",
                          "type": [
                            "boolean",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "category"
                      ],
                      "type": "object"
                    },
                    "maxItems": 16,
                    "minItems": 1,
                    "type": "array"
                  }
                },
                "required": [
                  "categories"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "categories": {
                          "description": "Every notification category, in display order. Security email is in none: it is always sent.",
                          "items": {
                            "properties": {
                              "category": {
                                "description": "The notification category.",
                                "enum": [
                                  "credits",
                                  "spend_limits",
                                  "jobs",
                                  "api_keys",
                                  "webhooks"
                                ],
                                "type": "string"
                              },
                              "email": {
                                "description": "Whether the owner is emailed (default on); null when the category sends no email.",
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              },
                              "in_app": {
                                "description": "Whether the dashboard shows it (default on). Webhooks always get every event.",
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "category",
                              "email",
                              "in_app"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "object": {
                          "description": "Always notification_preferences.",
                          "enum": [
                            "notification_preferences"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "categories"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Update notification preferences",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Update notification preferences",
        "tags": [
          "Notifications"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/notifications": {
      "get": {
        "description": "The account's events in the categories the dashboard shows, newest first, each with whether it is read. Free.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "notifications.list",
        "parameters": [
          {
            "description": "Notifications per page (default and maximum 100).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page; omit to start from the newest.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "category": {
                            "description": "The event type's notification category (catalog notification_categories).",
                            "enum": [
                              "credits",
                              "spend_limits",
                              "jobs",
                              "api_keys",
                              "webhooks"
                            ],
                            "type": "string"
                          },
                          "event": {
                            "description": "The event, exactly as GET /v1/events/{id} answers it.",
                            "properties": {
                              "data": {
                                "description": "The type's data object (small: a summary plus links)."
                              },
                              "id": {
                                "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                                "type": "string"
                              },
                              "object": {
                                "description": "Always event.",
                                "enum": [
                                  "event"
                                ],
                                "type": "string"
                              },
                              "timestamp": {
                                "description": "When it happened.",
                                "format": "date-time",
                                "type": "string"
                              },
                              "type": {
                                "description": "The event type (event types table); new types may be added.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "object",
                              "id",
                              "type",
                              "timestamp",
                              "data"
                            ],
                            "type": "object"
                          },
                          "object": {
                            "description": "Always notification.",
                            "enum": [
                              "notification"
                            ],
                            "type": "string"
                          },
                          "read": {
                            "description": "Whether it is at or before the read marker (POST /v1/notifications/read).",
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "object",
                          "category",
                          "read",
                          "event"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List the dashboard's notifications, newest first",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "List the dashboard's notifications, newest first",
        "tags": [
          "Notifications"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/notifications/read": {
      "post": {
        "description": "Marks an event (default: the newest) and every older one read; the marker only moves forward. Free.\n\n**Auth:** the dashboard session cookie.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "notifications.read",
        "parameters": [
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "through": {
                    "description": "Mark this event (a notification's event.id) and every older one read: the newest one shown. Default: the newest event.",
                    "maxLength": 64,
                    "minLength": 1,
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "object": {
                          "description": "Always notification_summary.",
                          "enum": [
                            "notification_summary"
                          ],
                          "type": "string"
                        },
                        "read_through": {
                          "description": "The newest event marked read (evt_…); null until one is. It may have expired since: events are kept events_retention_s.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "unread_count": {
                          "description": "Events after the read marker in the categories the dashboard shows (in_app on), counted up to 100.",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "object",
                        "unread_count",
                        "read_through"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Mark notifications read",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Mark notifications read",
        "tags": [
          "Notifications"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/notifications/summary": {
      "get": {
        "description": "How many notifications are unread, and the read marker. Free.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "notifications.summary",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "object": {
                          "description": "Always notification_summary.",
                          "enum": [
                            "notification_summary"
                          ],
                          "type": "string"
                        },
                        "read_through": {
                          "description": "The newest event marked read (evt_…); null until one is. It may have expired since: events are kept events_retention_s.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "unread_count": {
                          "description": "Events after the read marker in the categories the dashboard shows (in_app on), counted up to 100.",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "object",
                        "unread_count",
                        "read_through"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Count unread notifications",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Count unread notifications",
        "tags": [
          "Notifications"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/pillar/page": {
      "get": {
        "description": "Returns a public Pillar creator page with each link's click count, the products it sells and the audience its media kit shows. Products include courses, downloads and bookings, with their prices. The audience comes as an exact total and per account. The page also has the creator's name, bio, picture, banner, location, verified badge, join date, social accounts, featured videos and listed emails. Send a page name, a pillar.io link or the creator's ID.\n\nReturns `{data, meta}`: `data` is a `Profile` object (Pillar calls it a page) (the shared schema, the same on every platform). Null means unknown.\n\nIn Pillar's words: `metrics.follower_count` is audience.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/pillar/page/ (Markdown: https://socialtap.dev/docs/reference/pillar/page/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/pillar/page/index.md)",
          "url": "https://socialtap.dev/docs/reference/pillar/page/"
        },
        "operationId": "pillar.page.get",
        "parameters": [
          {
            "description": "The Pillar page: its name, with or without the @, a page link (pillar.io/ninja), or the creator's ID.",
            "example": "mytechceo",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Pillar page: its name, with or without the @, a page link (pillar.io/ninja), or the creator's ID.",
              "examples": [
                "ninja"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://athlane-file-management-prod.s3.amazonaws.com/cb9c2b15-f036-4813-922f-afb1cc87bd24",
                        "banner_url": null,
                        "bio": "Creating insightful tech comedy",
                        "category": null,
                        "country_code": null,
                        "created_at": "2024-04-14T23:57:20Z",
                        "display_name": "Jason Yeager",
                        "external_links": [
                          {
                            "title": "Instagram",
                            "url": "https://www.instagram.com/mytechceo"
                          },
                          {
                            "title": "LinkedIn",
                            "url": "https://www.linkedin.com/in/mytechceo/"
                          },
                          {
                            "title": "Twitter",
                            "url": "https://twitter.com/mytechceoo"
                          }
                        ],
                        "id": "ac41d280-faba-11ee-957a-7fb94fa87e77",
                        "is_private": null,
                        "is_verified": true,
                        "location": "Silicon Valley",
                        "metrics": {
                          "follower_count": 503358,
                          "following_count": null,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "pillar",
                        "platform_specific": {
                          "pillar": {
                            "audience": [
                              {
                                "channel_name": "mytechceo",
                                "follower_count": 368423,
                                "platform": "instagram"
                              },
                              {
                                "channel_name": "mytechceo",
                                "follower_count": 104635,
                                "platform": "tiktok"
                              }
                            ],
                            "contact_email": null,
                            "email": null,
                            "first_name": "Jason",
                            "full_name": "Jason Yeager",
                            "is_claimed": true,
                            "last_name": "Yeager",
                            "links": [
                              {
                                "click_count": 73,
                                "description": "Use $1,000 MyTechCEO discount",
                                "id": "593d0a1c-de0c-45a4-9db8-264837edbace",
                                "title": "Get Compliant with Vanta",
                                "url": "https://vanta.com/mytechceo"
                              }
                            ],
                            "products": [],
                            "socials": [
                              {
                                "platform": "instagram",
                                "url": "https://www.instagram.com/mytechceo"
                              },
                              {
                                "platform": "linkedin",
                                "url": "https://www.linkedin.com/in/mytechceo/"
                              },
                              {
                                "platform": "twitter",
                                "url": "https://twitter.com/mytechceoo"
                              }
                            ],
                            "videos": []
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://pillar.io/mytechceo",
                        "username": "mytechceo"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "pillar",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 992,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "ac41d280-faba-11ee-957a-7fb94fa87e77",
                          "url": "https://pillar.io/mytechceo"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/PillarPageResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Links with click counts, products and audience",
        "tags": [
          "Pillar"
        ],
        "x-socialtap-endpoint": "pillar.page",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/pinterest/board": {
      "get": {
        "description": "Returns a public Pinterest board from its link, a section's link, a pin.it short link or its ID. It has the name, description, cover, the owner, exact pin and follower counts, and the date it was created. It also says whether the board is collaborative, lists its collaborators, counts its sections and names the interests Pinterest relates it to. A section's link returns that section, with the board it belongs to.\n\nReturns `{data, meta}`: `data` is a `Playlist` object (Pinterest calls it a board) (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/pinterest/board/ (Markdown: https://socialtap.dev/docs/reference/pinterest/board/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/pinterest/board/index.md)",
          "url": "https://socialtap.dev/docs/reference/pinterest/board/"
        },
        "operationId": "pinterest.board.get",
        "parameters": [
          {
            "description": "The board: its link (pinterest.com/<username>/<board>/, also on a country's site such as uk.pinterest.com or pinterest.co.uk), a link to one of its sections (pinterest.com/ikeausa/living-rooms/sofas-armchairs/), a short link (pin.it/<code>) or its ID.",
            "example": "https://www.pinterest.com/chamberlaincoffeepins/the-wilderkind-collection/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The board: its link (pinterest.com/<username>/<board>/, also on a country's site such as uk.pinterest.com or pinterest.co.uk), a link to one of its sections (pinterest.com/ikeausa/living-rooms/sofas-armchairs/), a short link (pin.it/<code>) or its ID.",
              "examples": [
                "https://www.pinterest.com/pinterest/easy-and-chic-holiday-nail-ideas/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "description": "Inspired by the Pinterest Predicts trend, Wilderkind, this limited-edition collection is made for slowing down, getting outside, and finding beauty in everyday moments. #PinterestPartner",
                        "id": "1136033143445898365",
                        "is_collaborative": true,
                        "metrics": {
                          "post_count": 45
                        },
                        "owner": {
                          "avatar_url": "https://i.pinimg.com/280x280_RS/b1/a8/bd/b1a8bd69c78a85bf68ed7d613b978afe.jpg",
                          "display_name": "Chamberlain Coffee",
                          "id": "1136033212162710003",
                          "is_verified": false,
                          "url": "https://www.pinterest.com/chamberlaincoffeepins/",
                          "username": "chamberlaincoffeepins"
                        },
                        "platform": "pinterest",
                        "platform_specific": {
                          "pinterest": {
                            "board": null,
                            "collaborator_count": 3,
                            "collaborators": [
                              {
                                "avatar_url": "https://i.pinimg.com/280x280_RS/1c/b5/61/1cb561c8e7b9c709f78d110a4b5f0863.jpg",
                                "display_name": "Pinterest",
                                "id": "424605208526455283",
                                "is_verified": true,
                                "url": "https://www.pinterest.com/pinterest/",
                                "username": "pinterest"
                              },
                              {
                                "avatar_url": "https://i.pinimg.com/280x280_RS/fa/e4/eb/fae4eb8762dcd3d5e5186a2b034eafa2.jpg",
                                "display_name": "Pop Culture",
                                "id": "902057137772158742",
                                "is_verified": true,
                                "url": "https://www.pinterest.com/popculture/",
                                "username": "popculture"
                              },
                              {
                                "avatar_url": "https://i.pinimg.com/280x280_RS/50/64/63/50646339f8fb7668d5467c9356490d88.jpg",
                                "display_name": "emma chamberlain",
                                "id": "335729484630074012",
                                "is_verified": true,
                                "url": "https://www.pinterest.com/emmafranceschamberlain/",
                                "username": "emmafranceschamberlain"
                              }
                            ],
                            "created_at": "2026-09-10T22:22:46Z",
                            "follower_count": 8405,
                            "interests": [
                              "Emma Chamberlain",
                              "Find Beauty",
                              "Get Outside"
                            ],
                            "privacy": "public",
                            "section_count": 0
                          }
                        },
                        "platform_type": "board",
                        "thumbnail_url": "https://i.pinimg.com/474x/4c/90/fb/4c90fb11eaf57db4804c91cc4d8982fc.jpg",
                        "title": "The Wilderkind Collection",
                        "type": "collection",
                        "unknown_fields": [],
                        "url": "https://www.pinterest.com/chamberlaincoffeepins/the-wilderkind-collection/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "pinterest",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "playlist",
                          "id": "1136033143445898365",
                          "url": "https://www.pinterest.com/chamberlaincoffeepins/the-wilderkind-collection/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/PinterestBoardResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Board with exact pins, followers and collaborators",
        "tags": [
          "Pinterest"
        ],
        "x-socialtap-endpoint": "pinterest.board",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "playlist",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/pinterest/board_pins": {
      "get": {
        "description": "Returns the pins of a public Pinterest board from its link, pin.it short link or ID, or the pins of one section from the section's link. Each pin has its title, description, picture or video files with their sizes, exact saves and reactions, the page it links to, the pinner and the account that first pinned it. Page through the whole board with the cursor.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Post` items (Pinterest calls it a pin) (the shared schema, the same on every platform), Pinterest's order for logged-out visitors: mostly the latest saved first, with a few pins it picks moved to the top. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Pinterest's words: `metrics.like_count` is reactions, `metrics.save_count` is saves.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/pinterest/board_pins/ (Markdown: https://socialtap.dev/docs/reference/pinterest/board_pins/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/pinterest/board_pins/index.md)",
          "url": "https://socialtap.dev/docs/reference/pinterest/board_pins/"
        },
        "operationId": "pinterest.board_pins.list",
        "parameters": [
          {
            "description": "The board: its link (pinterest.com/<username>/<board>/, also on a country's site such as uk.pinterest.com or pinterest.co.uk), a section's link (pinterest.com/<username>/<board>/<section_name>/) for that section's pins, a short link (pin.it/<code>) or the board's ID.",
            "example": "https://www.pinterest.com/giphy/best-gifs/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The board: its link (pinterest.com/<username>/<board>/, also on a country's site such as uk.pinterest.com or pinterest.co.uk), a section's link (pinterest.com/<username>/<board>/<section_name>/) for that section's pins, a short link (pin.it/<code>) or the board's ID.",
              "examples": [
                "https://www.pinterest.com/pinterest/easy-and-chic-holiday-nail-ideas/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i.pinimg.com/280x280_RS/f3/a9/1b/f3a91b786c4e9ad0646de1388871c331.jpg",
                            "display_name": "GIPHY",
                            "id": "493636946564764083",
                            "is_verified": false,
                            "url": "https://www.pinterest.com/giphy/",
                            "username": "giphy"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "e1_AfqPShwBVp5ZokaT5khmGRiwRiGqtei_y-FH7Ja8X5R6VT4xupTL",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 1067,
                              "thumbnail_url": "https://i.pinimg.com/originals/0c/06/20/0c062027526cb5ea955f68145fc430c0.gif",
                              "type": "gif",
                              "url": "https://i.pinimg.com/originals/0c/06/20/0c062027526cb5ea955f68145fc430c0.gif",
                              "width": 480
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 12,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 185,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "author_follower_count": null,
                              "board": {
                                "id": "493636877845977605",
                                "title": "Best GIFs!",
                                "url": "https://www.pinterest.com/giphy/best-gifs/"
                              },
                              "caption_languages": [],
                              "domain": "medium.com",
                              "dominant_color": "#444477",
                              "interests": [],
                              "is_ad": false,
                              "is_author_verified_merchant": false,
                              "is_repin": false,
                              "link_url": "https://medium.com/@giphy/compassion-virtual-events-and-holidays-lead-giphys-april-insights-78b7adb09431",
                              "original_pinner": {
                                "avatar_url": "https://i.pinimg.com/280x280_RS/f3/a9/1b/f3a91b786c4e9ad0646de1388871c331.jpg",
                                "display_name": "GIPHY",
                                "id": "493636946564764083",
                                "is_verified": false,
                                "url": "https://www.pinterest.com/giphy/",
                                "username": "giphy"
                              },
                              "repin_count": 177,
                              "rich_type": "article"
                            }
                          },
                          "platform_type": "pin",
                          "published_at": "2020-05-07T14:46:12Z",
                          "text": null,
                          "thumbnail_url": "https://i.pinimg.com/originals/0c/06/20/0c062027526cb5ea955f68145fc430c0.gif",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [
                            "platform_specific.pinterest.interests"
                          ],
                          "url": "https://www.pinterest.com/pin/e1_AfqPShwBVp5ZokaT5khmGRiwRiGqtei_y-FH7Ja8X5R6VT4xupTL/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i.pinimg.com/280x280_RS/f3/a9/1b/f3a91b786c4e9ad0646de1388871c331.jpg",
                            "display_name": "GIPHY",
                            "id": "493636946564764083",
                            "is_verified": false,
                            "url": "https://www.pinterest.com/giphy/",
                            "username": "giphy"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "e1_AfqPShx_93vkYha4fXkGKz4d5W8bAC00UIJf5ygYQ5a810vu6yg_",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": "the text reads, 2020 year in review on a black background with pink and purple squares",
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 375,
                              "thumbnail_url": "https://i.pinimg.com/originals/d9/b3/d2/d9b3d2accbee36003a039826fa6fa455.gif",
                              "type": "gif",
                              "url": "https://i.pinimg.com/originals/d9/b3/d2/d9b3d2accbee36003a039826fa6fa455.gif",
                              "width": 750
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 3,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 71,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "author_follower_count": null,
                              "board": {
                                "id": "493636877845977605",
                                "title": "Best GIFs!",
                                "url": "https://www.pinterest.com/giphy/best-gifs/"
                              },
                              "caption_languages": [],
                              "domain": "giphy.medium.com",
                              "dominant_color": "#141414",
                              "interests": [],
                              "is_ad": false,
                              "is_author_verified_merchant": false,
                              "is_repin": false,
                              "link_url": "https://giphy.medium.com/giphys-most-viewed-gifs-of-2020-f198557f0080",
                              "original_pinner": null,
                              "repin_count": 64,
                              "rich_type": "article"
                            }
                          },
                          "platform_type": "pin",
                          "published_at": "2020-12-01T15:41:37Z",
                          "text": null,
                          "thumbnail_url": "https://i.pinimg.com/originals/d9/b3/d2/d9b3d2accbee36003a039826fa6fa455.gif",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [
                            "platform_specific.pinterest.interests"
                          ],
                          "url": "https://www.pinterest.com/pin/e1_AfqPShx_93vkYha4fXkGKz4d5W8bAC00UIJf5ygYQ5a810vu6yg_/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i.pinimg.com/280x280_RS/f3/a9/1b/f3a91b786c4e9ad0646de1388871c331.jpg",
                            "display_name": "GIPHY",
                            "id": "493636946564764083",
                            "is_verified": false,
                            "url": "https://www.pinterest.com/giphy/",
                            "username": "giphy"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "e1_AfqPShzsdXeagQPfHhFlJl0p6GhC23D3tyYmQMyvJTWRiKCh1KYz",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": "the zodiac sign is in front of a blue background with an image of a woman and two",
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 1920,
                              "thumbnail_url": "https://i.pinimg.com/originals/ca/aa/4b/caaa4bfeeaf1611db85fc1f9d35980df.gif",
                              "type": "gif",
                              "url": "https://i.pinimg.com/originals/ca/aa/4b/caaa4bfeeaf1611db85fc1f9d35980df.gif",
                              "width": 1080
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 0,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 9,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "author_follower_count": null,
                              "board": {
                                "id": "493636877845977605",
                                "title": "Best GIFs!",
                                "url": "https://www.pinterest.com/giphy/best-gifs/"
                              },
                              "caption_languages": [],
                              "domain": "giphy.com",
                              "dominant_color": "#20aab9",
                              "interests": [],
                              "is_ad": false,
                              "is_author_verified_merchant": false,
                              "is_repin": false,
                              "link_url": "https://giphy.com/stories/zodiac-d010c61c-f7e3",
                              "original_pinner": {
                                "avatar_url": "https://i.pinimg.com/280x280_RS/f3/a9/1b/f3a91b786c4e9ad0646de1388871c331.jpg",
                                "display_name": "GIPHY",
                                "id": "493636946564764083",
                                "is_verified": false,
                                "url": "https://www.pinterest.com/giphy/",
                                "username": "giphy"
                              },
                              "repin_count": 8,
                              "rich_type": "classifier data"
                            }
                          },
                          "platform_type": "pin",
                          "published_at": "2020-01-23T19:00:03Z",
                          "text": "It's the year on the Rat.",
                          "thumbnail_url": "https://i.pinimg.com/originals/ca/aa/4b/caaa4bfeeaf1611db85fc1f9d35980df.gif",
                          "title": "What's Your Zodiac Sign?",
                          "type": "image",
                          "unknown_fields": [
                            "platform_specific.pinterest.interests"
                          ],
                          "url": "https://www.pinterest.com/pin/e1_AfqPShzsdXeagQPfHhFlJl0p6GhC23D3tyYmQMyvJTWRiKCh1KYz/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "pinterest",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "playlist",
                          "id": "493636877845977605",
                          "url": "https://www.pinterest.com/giphy/best-gifs/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/PinterestBoard_pinsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Pins saved to a board, page by page",
        "tags": [
          "Pinterest"
        ],
        "x-socialtap-endpoint": "pinterest.board_pins",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Pinterest's order for logged-out visitors: mostly the latest saved first, with a few pins it picks moved to the top",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/pinterest/boards": {
      "get": {
        "description": "Returns a public Pinterest account's boards from its username, profile link or account ID. Each board has its name, description, link, cover picture, exact pin count and owner. Boards come in the order the profile shows them, including group boards the account joined, and the list pages on.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Playlist` items (Pinterest calls it a board) (the shared schema, the same on every platform), the order the account's profile shows its boards in: its own arrangement (A to Z, or one it set by hand), else the boards saved to most recently first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/pinterest/boards/ (Markdown: https://socialtap.dev/docs/reference/pinterest/boards/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/pinterest/boards/index.md)",
          "url": "https://socialtap.dev/docs/reference/pinterest/boards/"
        },
        "operationId": "pinterest.boards.list",
        "parameters": [
          {
            "description": "The Pinterest account: its username (any case, with or without the @), its profile link (pinterest.com/pinterest/, any tab of it, also on a country's site such as uk.pinterest.com or pinterest.co.uk) or its numeric account ID.",
            "example": "pinterest",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Pinterest account: its username (any case, with or without the @), its profile link (pinterest.com/pinterest/, any tab of it, also on a country's site such as uk.pinterest.com or pinterest.co.uk) or its numeric account ID.",
              "examples": [
                "pinterest"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "description": "Looking for something festive, or a whimsical twist on your go-to? Look no further with these festive nail ideas.",
                          "id": "424605139808130646",
                          "is_collaborative": false,
                          "metrics": {
                            "post_count": 38
                          },
                          "owner": {
                            "avatar_url": "https://i.pinimg.com/280x280_RS/1c/b5/61/1cb561c8e7b9c709f78d110a4b5f0863.jpg",
                            "display_name": "Pinterest",
                            "id": "424605208526455283",
                            "is_verified": true,
                            "url": "https://www.pinterest.com/pinterest/",
                            "username": "pinterest"
                          },
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "board": null,
                              "collaborator_count": 0,
                              "collaborators": [],
                              "created_at": "2026-11-06T16:15:44Z",
                              "follower_count": 4234204,
                              "interests": [],
                              "privacy": "public",
                              "section_count": 0
                            }
                          },
                          "platform_type": "board",
                          "thumbnail_url": "https://i.pinimg.com/474x/5f/48/5a/5f485ad1802b351b92be22f227432399.jpg",
                          "title": "Easy and chic holiday nail ideas",
                          "type": "collection",
                          "unknown_fields": [
                            "platform_specific.pinterest.collaborators",
                            "platform_specific.pinterest.interests"
                          ],
                          "url": "https://www.pinterest.com/pinterest/easy-and-chic-holiday-nail-ideas/"
                        },
                        {
                          "approximate_fields": [],
                          "description": "\"Wait, you haven't tried this before?\" Prepare to be the talk of the town this holiday with these simple-yet-impressive kitchen gifts.",
                          "id": "424605139808130353",
                          "is_collaborative": true,
                          "metrics": {
                            "post_count": 24
                          },
                          "owner": {
                            "avatar_url": "https://i.pinimg.com/280x280_RS/1c/b5/61/1cb561c8e7b9c709f78d110a4b5f0863.jpg",
                            "display_name": "Pinterest",
                            "id": "424605208526455283",
                            "is_verified": true,
                            "url": "https://www.pinterest.com/pinterest/",
                            "username": "pinterest"
                          },
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "board": null,
                              "collaborator_count": 1,
                              "collaborators": [],
                              "created_at": "2026-11-03T21:36:44Z",
                              "follower_count": 4234200,
                              "interests": [],
                              "privacy": "public",
                              "section_count": 0
                            }
                          },
                          "platform_type": "board",
                          "thumbnail_url": "https://i.pinimg.com/474x/5b/c0/70/5bc070b792408c674d208a004da190e3.jpg",
                          "title": "Kitchen gamechangers under $50",
                          "type": "collection",
                          "unknown_fields": [
                            "platform_specific.pinterest.collaborators",
                            "platform_specific.pinterest.interests"
                          ],
                          "url": "https://www.pinterest.com/pinterest/kitchen-gamechangers-under-50/"
                        },
                        {
                          "approximate_fields": [],
                          "description": "One for you, one for your bestie, or that really cool niece who already has everything.",
                          "id": "424605139808129612",
                          "is_collaborative": false,
                          "metrics": {
                            "post_count": 44
                          },
                          "owner": {
                            "avatar_url": "https://i.pinimg.com/280x280_RS/1c/b5/61/1cb561c8e7b9c709f78d110a4b5f0863.jpg",
                            "display_name": "Pinterest",
                            "id": "424605208526455283",
                            "is_verified": true,
                            "url": "https://www.pinterest.com/pinterest/",
                            "username": "pinterest"
                          },
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "board": null,
                              "collaborator_count": 0,
                              "collaborators": [],
                              "created_at": "2026-10-27T23:56:15Z",
                              "follower_count": 4234206,
                              "interests": [],
                              "privacy": "public",
                              "section_count": 0
                            }
                          },
                          "platform_type": "board",
                          "thumbnail_url": "https://i.pinimg.com/474x/bb/79/4d/bb794d74fa828232295a65c60224734c.jpg",
                          "title": "Everything it-girls are buying this year",
                          "type": "collection",
                          "unknown_fields": [
                            "platform_specific.pinterest.collaborators",
                            "platform_specific.pinterest.interests"
                          ],
                          "url": "https://www.pinterest.com/pinterest/everything-it-girls-are-buying-this-year/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "pinterest",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "424605208526455283",
                          "url": "https://www.pinterest.com/pinterest/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/PinterestBoardsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Account's boards with pin counts, covers and links",
        "tags": [
          "Pinterest"
        ],
        "x-socialtap-endpoint": "pinterest.boards",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the order the account's profile shows its boards in: its own arrangement (A to Z, or one it set by hand), else the boards saved to most recently first",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "playlist",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/pinterest/pin": {
      "get": {
        "description": "Returns a public Pinterest pin from its link, pin.it short link or ID. It has the title, description, hashtags, picture or video files with their sizes, and exact saves, reactions, comments and shares. It also has the page the pin links to, its board, the pinner and the account that first pinned it, and the interests Pinterest files it under. Idea and carousel pins list every page.\n\nReturns `{data, meta}`: `data` is a `Post` object (Pinterest calls it a pin) (the shared schema, the same on every platform). Null means unknown.\n\nIn Pinterest's words: `metrics.like_count` is reactions, `metrics.save_count` is saves.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/pinterest/pin/ (Markdown: https://socialtap.dev/docs/reference/pinterest/pin/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/pinterest/pin/index.md)",
          "url": "https://socialtap.dev/docs/reference/pinterest/pin/"
        },
        "operationId": "pinterest.pin.get",
        "parameters": [
          {
            "description": "The pin: its link (pinterest.com/pin/424605071146283650/, also on a country's site such as uk.pinterest.com or pinterest.co.uk, its pinterest.com/pin/<words>--<id>/ link, its AMP page), a short link (pin.it/<code>) or its ID.",
            "example": "https://www.pinterest.com/pin/424605071146283650/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The pin: its link (pinterest.com/pin/424605071146283650/, also on a country's site such as uk.pinterest.com or pinterest.co.uk, its pinterest.com/pin/<words>--<id>/ link, its AMP page), a short link (pin.it/<code>) or its ID.",
              "examples": [
                "https://www.pinterest.com/pin/424605071146283650/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://i.pinimg.com/280x280_RS/1c/b5/61/1cb561c8e7b9c709f78d110a4b5f0863.jpg",
                          "display_name": "Pinterest",
                          "id": "424605208526455283",
                          "is_verified": true,
                          "url": "https://www.pinterest.com/pinterest/",
                          "username": "pinterest"
                        },
                        "coauthors": [],
                        "duration_ms": 15533,
                        "hashtags": [],
                        "id": "424605071146283650",
                        "is_nsfw": null,
                        "is_pinned": null,
                        "is_sponsored": false,
                        "language": null,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": 15533,
                            "expires_at": null,
                            "height": 1920,
                            "thumbnail_url": "https://i.pinimg.com/videos/thumbnails/originals/13/cb/ac/13cbacafb8cf248f7734f941ab31301f.0000000.jpg",
                            "type": "video",
                            "url": "https://v1.pinimg.com/videos/mc/720p/13/cb/ac/13cbacafb8cf248f7734f941ab31301f.mp4",
                            "width": 1080
                          }
                        ],
                        "mentions": [
                          "overglowedit"
                        ],
                        "metrics": {
                          "comment_count": 2,
                          "like_count": 245,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": 534,
                          "share_count": 0,
                          "view_count": null
                        },
                        "platform": "pinterest",
                        "platform_specific": {
                          "pinterest": {
                            "author_follower_count": 6269070,
                            "board": {
                              "id": "424605139808130646",
                              "title": "Easy and chic holiday nail ideas",
                              "url": "https://www.pinterest.com/pinterest/easy-and-chic-holiday-nail-ideas/"
                            },
                            "caption_languages": [],
                            "domain": null,
                            "dominant_color": "#7b7169",
                            "interests": [
                              "Star Nail Designs",
                              "Star Nail Art",
                              "Nail Designs Tutorial"
                            ],
                            "is_ad": false,
                            "is_author_verified_merchant": false,
                            "is_repin": true,
                            "link_url": null,
                            "original_pinner": {
                              "avatar_url": "https://i.pinimg.com/280x280_RS/cb/9a/d8/cb9ad83a486ef2ed5348c999dbb56564.jpg",
                              "display_name": "Overglow Edit",
                              "id": "101683041495156533",
                              "is_verified": false,
                              "url": "https://www.pinterest.com/overglowedit/",
                              "username": "overglowedit"
                            },
                            "repin_count": 5,
                            "rich_type": null
                          }
                        },
                        "platform_type": "idea_pin",
                        "published_at": "2026-11-06T16:28:27Z",
                        "text": "Follow @OverglowEdit for more nail inspo! Holiday nails, star nails, diy nail art, star nail art, fun holiday nails, holiday party nails",
                        "thumbnail_url": "https://i.pinimg.com/originals/bb/be/20/bbbe20442a8eb79de9959519808c2506.jpg",
                        "title": "Holiday Star Nails Tutorial - trendy nails, fall nails, Christmas nails, nail inspo, nail art",
                        "type": "video",
                        "unknown_fields": [],
                        "url": "https://www.pinterest.com/pin/424605071146283650/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "pinterest",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "424605071146283650",
                          "url": "https://www.pinterest.com/pin/424605071146283650/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/PinterestPinResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Pin with saves, reactions, media and its link",
        "tags": [
          "Pinterest"
        ],
        "x-socialtap-endpoint": "pinterest.pin",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/pinterest/pins": {
      "get": {
        "description": "Returns a public Pinterest account's pins from its username, profile link or ID, newest first, page by page. Each pin has its title, description, hashtags, picture or video files, exact saves, reactions and comments, the page it links to, its board and the account that first pinned it. List every pin the account saved, or only the ones it created.\n\nReturns `{data, page, meta}`: `data` holds up to 25 `Post` items (Pinterest calls it a pin) (the shared schema, the same on every platform), newest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Pinterest's words: `metrics.like_count` is reactions, `metrics.save_count` is saves.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/pinterest/pins/ (Markdown: https://socialtap.dev/docs/reference/pinterest/pins/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/pinterest/pins/index.md)",
          "url": "https://socialtap.dev/docs/reference/pinterest/pins/"
        },
        "operationId": "pinterest.pins.list",
        "parameters": [
          {
            "description": "The Pinterest account: its username (any case, with or without the @), its profile link (pinterest.com/<username>/, any of its tabs such as /_created/ or /_pins/, also on a country's site such as uk.pinterest.com or pinterest.co.uk) or its numeric ID.",
            "example": "pinterest",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Pinterest account: its username (any case, with or without the @), its profile link (pinterest.com/<username>/, any of its tabs such as /_created/ or /_pins/, also on a country's site such as uk.pinterest.com or pinterest.co.uk) or its numeric ID.",
              "examples": [
                "pinterest"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. A saved pin counts from when the account saved it. On tab=saved it only filters each page, as Pinterest can list a pin out of order there; on tab=created paging stops once it is reached.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. A saved pin counts from when the account saved it. On tab=saved it only filters each page, as Pinterest can list a pin out of order there; on tab=created paging stops once it is reached.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Which pins: saved (default), every pin the account saved, its own and the ones it saved from others, as its profile's Pins tab lists them; created, the pins it made itself (its Created tab). A link to the account's /_created/ tab sent without tab lists created.",
            "example": "created",
            "in": "query",
            "name": "tab",
            "schema": {
              "description": "Which pins: saved (default), every pin the account saved, its own and the ones it saved from others, as its profile's Pins tab lists them; created, the pins it made itself (its Created tab). A link to the account's /_created/ tab sent without tab lists created.",
              "enum": [
                "saved",
                "created"
              ],
              "examples": [
                "created"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 25,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 25,
              "maximum": 25,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i.pinimg.com/280x280_RS/1c/b5/61/1cb561c8e7b9c709f78d110a4b5f0863.jpg",
                            "display_name": "Pinterest",
                            "id": "424605208526455283",
                            "is_verified": true,
                            "url": "https://www.pinterest.com/pinterest/",
                            "username": "pinterest"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "424605071146306109",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 1599,
                              "thumbnail_url": "https://i.pinimg.com/originals/e3/b2/88/e3b288ad73798578086a4bcafde8eafd.jpg",
                              "type": "image",
                              "url": "https://i.pinimg.com/originals/e3/b2/88/e3b288ad73798578086a4bcafde8eafd.jpg",
                              "width": 1199
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 0,
                            "like_count": 9,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 323,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "author_follower_count": 6269070,
                              "board": {
                                "id": "424605139808130646",
                                "title": "Easy and chic holiday nail ideas",
                                "url": "https://www.pinterest.com/pinterest/easy-and-chic-holiday-nail-ideas/"
                              },
                              "caption_languages": [],
                              "domain": null,
                              "dominant_color": "#563a27",
                              "interests": [],
                              "is_ad": false,
                              "is_author_verified_merchant": false,
                              "is_repin": true,
                              "link_url": null,
                              "original_pinner": {
                                "avatar_url": "https://i.pinimg.com/280x280_RS/4a/7e/c4/4a7ec41a64ea9df0a2a34d0e22834c9c.jpg",
                                "display_name": "Lauren",
                                "id": "631770791385517160",
                                "is_verified": false,
                                "url": "https://www.pinterest.com/lrnglenn/",
                                "username": "lrnglenn"
                              },
                              "repin_count": null,
                              "rich_type": null
                            }
                          },
                          "platform_type": "idea_pin",
                          "published_at": "2026-11-09T19:14:02Z",
                          "text": null,
                          "thumbnail_url": "https://i.pinimg.com/originals/e3/b2/88/e3b288ad73798578086a4bcafde8eafd.jpg",
                          "title": "🪩✨",
                          "type": "image",
                          "unknown_fields": [
                            "platform_specific.pinterest.interests"
                          ],
                          "url": "https://www.pinterest.com/pin/424605071146306109/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i.pinimg.com/280x280_RS/1c/b5/61/1cb561c8e7b9c709f78d110a4b5f0863.jpg",
                            "display_name": "Pinterest",
                            "id": "424605208526455283",
                            "is_verified": true,
                            "url": "https://www.pinterest.com/pinterest/",
                            "username": "pinterest"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [
                            "beyoncé",
                            "nailtech"
                          ],
                          "id": "424605071146306108",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 1666,
                              "thumbnail_url": "https://i.pinimg.com/originals/e3/9e/69/e39e69304ea39fffbfa904935faff40b.jpg",
                              "type": "image",
                              "url": "https://i.pinimg.com/originals/e3/9e/69/e39e69304ea39fffbfa904935faff40b.jpg",
                              "width": 1440
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 0,
                            "like_count": 8,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 187,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "author_follower_count": 6269070,
                              "board": {
                                "id": "424605139808130646",
                                "title": "Easy and chic holiday nail ideas",
                                "url": "https://www.pinterest.com/pinterest/easy-and-chic-holiday-nail-ideas/"
                              },
                              "caption_languages": [],
                              "domain": "instagram.com",
                              "dominant_color": "#93897f",
                              "interests": [],
                              "is_ad": false,
                              "is_author_verified_merchant": false,
                              "is_repin": true,
                              "link_url": "https://www.instagram.com/p/DJvUrGMgyJQ/",
                              "original_pinner": {
                                "avatar_url": "https://i.pinimg.com/280x280_RS/7d/d4/67/7dd467eb766ae86468f9423e86ff1743.jpg",
                                "display_name": "Nicxbeauttyy",
                                "id": "1009510210131239142",
                                "is_verified": false,
                                "url": "https://www.pinterest.com/nicxbeautty/",
                                "username": "nicxbeautty"
                              },
                              "repin_count": null,
                              "rich_type": null
                            }
                          },
                          "platform_type": "pin",
                          "published_at": "2026-11-09T19:13:44Z",
                          "text": "A moment for the disco nails #beyoncé #nailtech",
                          "thumbnail_url": "https://i.pinimg.com/originals/e3/9e/69/e39e69304ea39fffbfa904935faff40b.jpg",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [
                            "platform_specific.pinterest.interests"
                          ],
                          "url": "https://www.pinterest.com/pin/424605071146306108/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i.pinimg.com/280x280_RS/1c/b5/61/1cb561c8e7b9c709f78d110a4b5f0863.jpg",
                            "display_name": "Pinterest",
                            "id": "424605208526455283",
                            "is_verified": true,
                            "url": "https://www.pinterest.com/pinterest/",
                            "username": "pinterest"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "424605071146306107",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 1211,
                              "thumbnail_url": "https://i.pinimg.com/originals/80/d8/c9/80d8c92c74168ea8c66d5681d0b719d4.jpg",
                              "type": "image",
                              "url": "https://i.pinimg.com/originals/80/d8/c9/80d8c92c74168ea8c66d5681d0b719d4.jpg",
                              "width": 1014
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 0,
                            "like_count": 5,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 189,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "author_follower_count": 6269070,
                              "board": {
                                "id": "424605139808130646",
                                "title": "Easy and chic holiday nail ideas",
                                "url": "https://www.pinterest.com/pinterest/easy-and-chic-holiday-nail-ideas/"
                              },
                              "caption_languages": [],
                              "domain": null,
                              "dominant_color": "#aa8878",
                              "interests": [],
                              "is_ad": false,
                              "is_author_verified_merchant": false,
                              "is_repin": true,
                              "link_url": null,
                              "original_pinner": {
                                "avatar_url": "https://i.pinimg.com/280x280_RS/81/1c/32/811c32b5bf66eecd20d7185caf897909.jpg",
                                "display_name": "Kimberly Reyn",
                                "id": "431712451688407077",
                                "is_verified": false,
                                "url": "https://www.pinterest.com/amazon_chic/",
                                "username": "amazon_chic"
                              },
                              "repin_count": null,
                              "rich_type": null
                            }
                          },
                          "platform_type": "idea_pin",
                          "published_at": "2026-11-09T19:13:38Z",
                          "text": "Nail idea for the holidays",
                          "thumbnail_url": "https://i.pinimg.com/originals/80/d8/c9/80d8c92c74168ea8c66d5681d0b719d4.jpg",
                          "title": "Christmas | Holiday Set",
                          "type": "image",
                          "unknown_fields": [
                            "platform_specific.pinterest.interests"
                          ],
                          "url": "https://www.pinterest.com/pin/424605071146306107/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "pinterest",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "424605208526455283",
                          "url": "https://www.pinterest.com/pinterest/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/PinterestPinsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Every pin an account saved or created, page by page",
        "tags": [
          "Pinterest"
        ],
        "x-socialtap-endpoint": "pinterest.pins",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "page_max": 25,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/pinterest/profile": {
      "get": {
        "description": "Returns a public Pinterest account from its username, profile link or ID. It has exact follower, following, pin and board counts, its monthly views, the bio, website and linked Instagram account, the picture and cover, the join date and when it last saved a pin. Badges say whether it is verified, a business account or a verified merchant.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\nIn Pinterest's words: `metrics.post_count` is pins.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/pinterest/profile/ (Markdown: https://socialtap.dev/docs/reference/pinterest/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/pinterest/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/pinterest/profile/"
        },
        "operationId": "pinterest.profile.get",
        "parameters": [
          {
            "description": "The Pinterest account: its username (any case, with or without the @), its profile link (pinterest.com/<username>/, any of its tabs such as /_created/ or /_saved/, also on a country's site such as uk.pinterest.com or pinterest.co.uk) or its numeric ID.",
            "example": "pinterest",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Pinterest account: its username (any case, with or without the @), its profile link (pinterest.com/<username>/, any of its tabs such as /_created/ or /_saved/, also on a country's site such as uk.pinterest.com or pinterest.co.uk) or its numeric ID.",
              "examples": [
                "pinterest"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "platform_specific.pinterest.monthly_view_count"
                        ],
                        "avatar_url": "https://i.pinimg.com/280x280_RS/1c/b5/61/1cb561c8e7b9c709f78d110a4b5f0863.jpg",
                        "banner_url": "https://i.pinimg.com/originals/68/e2/7f/68e27f34a51fda06520a4eca1c31a982.jpg",
                        "bio": "Find your reason to go offline. 📌",
                        "category": null,
                        "country_code": null,
                        "created_at": "2012-08-16T06:25:03Z",
                        "display_name": "Pinterest",
                        "external_links": [
                          {
                            "title": null,
                            "url": "http://www.pinterest.com"
                          }
                        ],
                        "id": "424605208526455283",
                        "is_private": false,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 6269072,
                          "following_count": 314,
                          "post_count": 98418,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "pinterest",
                        "platform_specific": {
                          "pinterest": {
                            "all_following_count": 398,
                            "interest_following_count": 0,
                            "is_business_account": true,
                            "is_verified_merchant": false,
                            "is_website_verified": true,
                            "last_post_at": "2026-11-09T19:14:02Z",
                            "monthly_view_count": 10000000,
                            "playlist_count": 168
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://www.pinterest.com/pinterest/",
                        "username": "pinterest"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "pinterest",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "424605208526455283",
                          "url": "https://www.pinterest.com/pinterest/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/PinterestProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact followers, pins, boards and monthly views",
        "tags": [
          "Pinterest"
        ],
        "x-socialtap-endpoint": "pinterest.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/pinterest/search_pins": {
      "get": {
        "description": "Returns the pins Pinterest's search shows for a keyword, a page at a time, in Pinterest's order. Each pin has its pictures or video, title and description, the link it saves, its board, the pinner with their follower count, reactions, when it was saved and the interests Pinterest files it under.\n\nReturns `{data, page, meta}`: `data` holds up to 25 `Post` items (Pinterest calls it a pin) (the shared schema, the same on every platform), Pinterest's own relevance order for the query. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Pinterest's words: `metrics.like_count` is reactions, `metrics.save_count` is saves.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/pinterest/search_pins/ (Markdown: https://socialtap.dev/docs/reference/pinterest/search_pins/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/pinterest/search_pins/index.md)",
          "url": "https://socialtap.dev/docs/reference/pinterest/search_pins/"
        },
        "operationId": "pinterest.search_pins.list",
        "parameters": [
          {
            "description": "What to search for, in any language, as you would type it in Pinterest's search box: words, a phrase, emoji. A Pinterest search link (pinterest.com/search/pins/?q=…) is read as its words.",
            "example": "nail art",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to search for, in any language, as you would type it in Pinterest's search box: words, a phrase, emoji. A Pinterest search link (pinterest.com/search/pins/?q=…) is read as its words.",
              "examples": [
                "nail art"
              ],
              "maxLength": 500,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 25,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 25,
              "maximum": 25,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i.pinimg.com/280x280_RS/ed/94/cd/ed94cd596ae3162a29a215670b26b7dd.jpg",
                            "display_name": "Depop",
                            "id": "189292127996348775",
                            "is_verified": false,
                            "url": "https://www.pinterest.com/depop/",
                            "username": "depop"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [
                            "acrylicnails",
                            "swirls",
                            "chrome"
                          ],
                          "id": "e1_AfqPShx1XVZpv_ISZ-VS4878xEn4fB0nwdJscpsd6xSthGtJwlWe9Q",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": "Multi-colored ombré swirl acrylic nails with silver chrome swirl embellishment rainbow #acrylicnails #swirls #chrome #custom #presson\n\nEach set is handmade by me with love! ♡\nPrice is for ONE complete set of press-on nails.\n\nSize:\n• XS\n• S\n• M\n• L\n• XL\n♡ Please double-check your …",
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 1280,
                              "thumbnail_url": "https://i.pinimg.com/originals/08/9c/1e/089c1eaf1df17e01c50616fc9d47bae2.jpg",
                              "type": "image",
                              "url": "https://i.pinimg.com/originals/08/9c/1e/089c1eaf1df17e01c50616fc9d47bae2.jpg",
                              "width": 1280
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 14,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "author_follower_count": 161666,
                              "board": {
                                "id": "189292059277314742",
                                "title": "Products",
                                "url": "https://www.pinterest.com/depop/_products/"
                              },
                              "caption_languages": [],
                              "domain": "depop.com",
                              "dominant_color": "#baa6a2",
                              "interests": [
                                "Silvar Nails",
                                "Squigly Nails",
                                "Nail Art Studs"
                              ],
                              "is_ad": false,
                              "is_author_verified_merchant": true,
                              "is_repin": null,
                              "link_url": "https://www.depop.com/products/nailsbyvicj-multi-colored-ombre-swirl-acrylic-nails-57e2/?pla_feed=US",
                              "original_pinner": null,
                              "repin_count": null,
                              "rich_type": "product"
                            }
                          },
                          "platform_type": "pin",
                          "published_at": "2026-10-16T01:29:18Z",
                          "text": "Multi-colored ombré swirl acrylic nails with silver chrome swirl embellishment rainbow #acrylicnails #swirls #chrome #custom #presson\n\nEach set is handmade by me with love! ♡\nPrice is for ONE complete set of press-on nails.\n\nSize:\n• XS\n• S\n• M\n• L\n• XL\n♡ Please double-check your …",
                          "thumbnail_url": "https://i.pinimg.com/originals/08/9c/1e/089c1eaf1df17e01c50616fc9d47bae2.jpg",
                          "title": "Depop Unisex Nails",
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://www.pinterest.com/pin/e1_AfqPShx1XVZpv_ISZ-VS4878xEn4fB0nwdJscpsd6xSthGtJwlWe9Q/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i.pinimg.com/280x280_RS/7f/d2/07/7fd207a1929860fd93ec684eb717a4b4.jpg",
                            "display_name": "Walmart",
                            "id": "112027246889273637",
                            "is_verified": true,
                            "url": "https://www.pinterest.com/walmart/",
                            "username": "walmart"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "e1_AfqPShzcXsfR3xPWrd6Muo58KSPWrQm1k9fyQsnJjD8aUqzpTeRGCw",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": "Elevate your nail game with our 24 Pieces Navy Blue and Yellow Polka Dot Star Press on Nails Set. This trendy nail art collection features a perfect blend of chic navy blue and playful yellow polka dots, complemented by star accents, making it ideal for any occasion. Whether you'…",
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 1200,
                              "thumbnail_url": "https://i.pinimg.com/originals/2d/e6/38/2de638c7f0f6c5c1a8c23fe31d6f0eba.jpg",
                              "type": "image",
                              "url": "https://i.pinimg.com/originals/2d/e6/38/2de638c7f0f6c5c1a8c23fe31d6f0eba.jpg",
                              "width": 1200
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 2,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "author_follower_count": 2307882,
                              "board": {
                                "id": "112027178170042638",
                                "title": "Products",
                                "url": "https://www.pinterest.com/walmart/_products/"
                              },
                              "caption_languages": [],
                              "domain": "walmart.com",
                              "dominant_color": "#79594d",
                              "interests": [
                                "Nail Eesigns",
                                "Gel X Nail Designs Almond Short",
                                "Trending Summer Nails Short Square"
                              ],
                              "is_ad": false,
                              "is_author_verified_merchant": true,
                              "is_repin": null,
                              "link_url": "https://www.walmart.com/ip/24-Pieces-Navy-Blue-and-Yellow-Polka-Dot-Star-Press-on-Nails-Set-Trendy-Nail-Art-for-Every-Occasion/20563271063?wmlspartner=wlpa&selectedSellerId=103119446",
                              "original_pinner": null,
                              "repin_count": null,
                              "rich_type": "product"
                            }
                          },
                          "platform_type": "pin",
                          "published_at": "2026-09-13T06:37:36Z",
                          "text": "Elevate your nail game with our 24 Pieces Navy Blue and Yellow Polka Dot Star Press on Nails Set. This trendy nail art collection features a perfect blend of chic navy blue and playful yellow polka dots, complemented by star accents, making it ideal for any occasion. Whether you'…",
                          "thumbnail_url": "https://i.pinimg.com/originals/2d/e6/38/2de638c7f0f6c5c1a8c23fe31d6f0eba.jpg",
                          "title": "24 Pieces Navy Blue and Yellow Polka Dot Star Press on Nails Set - Trendy Nail Art for Every Occasion",
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://www.pinterest.com/pin/e1_AfqPShzcXsfR3xPWrd6Muo58KSPWrQm1k9fyQsnJjD8aUqzpTeRGCw/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i.pinimg.com/280x280_RS/d1/84/c8/d184c8624cb409c8f6e4fcf8baf91cd2.jpg",
                            "display_name": "Etsy",
                            "id": "155304024558534660",
                            "is_verified": true,
                            "url": "https://www.pinterest.com/etsy/",
                            "username": "etsy"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "e1_AfqPShz7mhLYU-JOyXGGq4evbbMsKODcOgIj3LayXlAsznsy2SC3Mw",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": "Welcome to my shop! ✨ I'm so glad you're here--hope you find a style that speaks to you. 🛠️ I use only high-quality materials to create press-on nails that are sturdy, long-lasting, and made to be trusted. 💅 Wear them: 1-2 days with adhesive tabs (included with your set) 2-3 week…",
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 1800,
                              "thumbnail_url": "https://i.pinimg.com/originals/33/96/33/339633ec3d5d602aa4c2ec35f08d308e.jpg",
                              "type": "image",
                              "url": "https://i.pinimg.com/originals/33/96/33/339633ec3d5d602aa4c2ec35f08d308e.jpg",
                              "width": 1350
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 2129,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "author_follower_count": 11240119,
                              "board": {
                                "id": "155303955839369647",
                                "title": "Products",
                                "url": "https://www.pinterest.com/etsy/_products/"
                              },
                              "caption_languages": [],
                              "domain": "etsy.com",
                              "dominant_color": "#593727",
                              "interests": [
                                "Light Briwn Nails",
                                "Leapard Nails",
                                "Summer And Fall Nails"
                              ],
                              "is_ad": false,
                              "is_author_verified_merchant": true,
                              "is_repin": null,
                              "link_url": "https://www.etsy.com/listing/4507489889/leopard-print-press-on-nails-with-white",
                              "original_pinner": null,
                              "repin_count": null,
                              "rich_type": "product"
                            }
                          },
                          "platform_type": "pin",
                          "published_at": "2026-07-17T20:11:24Z",
                          "text": "Welcome to my shop! ✨ I'm so glad you're here--hope you find a style that speaks to you. 🛠️ I use only high-quality materials to create press-on nails that are sturdy, long-lasting, and made to be trusted. 💅 Wear them: 1-2 days with adhesive tabs (included with your set) 2-3 week…",
                          "thumbnail_url": "https://i.pinimg.com/originals/33/96/33/339633ec3d5d602aa4c2ec35f08d308e.jpg",
                          "title": "Leopard Print Press on Nails with White Floral Art, Brown Spots and Gold Accent, Trendy Animal Print Fake Nails, Reusable",
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://www.pinterest.com/pin/e1_AfqPShz7mhLYU-JOyXGGq4evbbMsKODcOgIj3LayXlAsznsy2SC3Mw/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "pinterest",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/PinterestSearch_pinsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Pins matching a keyword, with pictures and pinners",
        "tags": [
          "Pinterest"
        ],
        "x-socialtap-endpoint": "pinterest.search_pins",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Pinterest's own relevance order for the query",
          "page_max": 25,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/pinterest/top_trends": {
      "get": {
        "description": "Returns the searches trending on Pinterest in a country, from Pinterest Trends' top monthly, top yearly, growing and seasonal boards. Each term comes with its rank, how much it is searched against the board's top term, its weekly, monthly and yearly change, how seasonal it is and a link to its Pinterest search. Filter by interest, age, gender or keywords; with no parameters you get the US top monthly board.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Trend` items (the shared schema, the same on every platform), Pinterest Trends' rank for the board (1 = top). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/pinterest/top_trends/ (Markdown: https://socialtap.dev/docs/reference/pinterest/top_trends/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/pinterest/top_trends/index.md)",
          "url": "https://socialtap.dev/docs/reference/pinterest/top_trends/"
        },
        "operationId": "pinterest.top_trends.list",
        "parameters": [
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The country whose searches to rank: US, CA, GB, DE, FR, IT, ES, MX, AR, CO, BR, ID, IN, MY, PH, TH, SA, EG, TR or KR, each with a board of its own; or IE, AT, CH, PT, GR, MT, SE, DK, FI, NO, NL, BE, LU, PL, RO, HU, SK, CZ, CL, AU, NZ, CR, DO, EC, GT, PE or CY, which Pinterest counts together with their neighbors: those read the shared board, and market_country_codes names its countries.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "default": "US",
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The country whose searches to rank: US, CA, GB, DE, FR, IT, ES, MX, AR, CO, BR, ID, IN, MY, PH, TH, SA, EG, TR or KR, each with a board of its own; or IE, AT, CH, PT, GR, MT, SE, DK, FI, NO, NL, BE, LU, PL, RO, HU, SK, CZ, CL, AU, NZ, CR, DO, EC, GT, PE or CY, which Pinterest counts together with their neighbors: those read the shared board, and market_country_codes names its countries.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Which board: top_monthly (the default: the most searched terms this month), top_yearly (this year), growing (the terms whose searches rose most this month) or seasonal (terms searched at this time every year, now rising).",
            "example": "growing",
            "in": "query",
            "name": "kind",
            "schema": {
              "default": "top_monthly",
              "description": "Which board: top_monthly (the default: the most searched terms this month), top_yearly (this year), growing (the terms whose searches rose most this month) or seasonal (terms searched at this time every year, now rising).",
              "enum": [
                "top_monthly",
                "top_yearly",
                "growing",
                "seasonal"
              ],
              "examples": [
                "growing"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only terms Pinterest files under this interest, and each term's categories filled in. Omit for every interest.",
            "example": "beauty",
            "in": "query",
            "name": "category",
            "schema": {
              "description": "Only terms Pinterest files under this interest, and each term's categories filled in. Omit for every interest.",
              "enum": [
                "womens_fashion",
                "mens_fashion",
                "childrens_fashion",
                "beauty",
                "health",
                "design",
                "wedding",
                "travel",
                "gardening",
                "finance",
                "vehicles",
                "architecture",
                "food_and_drinks",
                "sport",
                "parenting",
                "education",
                "animals",
                "diy_and_crafts",
                "home_decor",
                "event_planning",
                "quotes",
                "entertainment",
                "electronics",
                "art"
              ],
              "examples": [
                "beauty"
              ],
              "type": "string"
            }
          },
          {
            "description": "Rank by the searches of people of this age only.",
            "example": "25-34",
            "in": "query",
            "name": "age",
            "schema": {
              "description": "Rank by the searches of people of this age only.",
              "enum": [
                "18-24",
                "25-34",
                "35-44",
                "45-49",
                "50-54",
                "55-64",
                "65-plus"
              ],
              "examples": [
                "25-34"
              ],
              "type": "string"
            }
          },
          {
            "description": "Rank by the searches of people of this gender only (unspecified: those who gave none).",
            "example": "female",
            "in": "query",
            "name": "gender",
            "schema": {
              "description": "Rank by the searches of people of this gender only (unspecified: those who gave none).",
              "enum": [
                "female",
                "male",
                "unspecified"
              ],
              "examples": [
                "female"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only terms containing one of these keywords, comma-separated (at most ten).",
            "example": "nails",
            "in": "query",
            "name": "contains",
            "schema": {
              "description": "Only terms containing one of these keywords, comma-separated (at most ten).",
              "examples": [
                "nails"
              ],
              "type": "string"
            }
          },
          {
            "description": "Leave out terms containing any of these keywords, comma-separated (at most ten).",
            "example": "halloween",
            "in": "query",
            "name": "excludes",
            "schema": {
              "description": "Leave out terms containing any of these keywords, comma-separated (at most ten).",
              "examples": [
                "halloween"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "platform_specific.pinterest.weekly_change",
                            "platform_specific.pinterest.monthly_change",
                            "platform_specific.pinterest.yearly_change"
                          ],
                          "categories": [],
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "country_code": "US",
                              "history": [],
                              "market_country_codes": [
                                "US"
                              ],
                              "monthly_change": -0.1,
                              "period_end_at": "2026-11-07T00:00:00Z",
                              "search_index": 100,
                              "seasonality": 0.9816409,
                              "weekly_change": 0.1,
                              "yearly_change": 0.2
                            }
                          },
                          "rank": 1,
                          "term": "fall nails",
                          "thumbnail_url": null,
                          "unknown_fields": [
                            "categories",
                            "platform_specific.pinterest.history"
                          ],
                          "url": "https://www.pinterest.com/search/pins/?q=fall+nails"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.pinterest.weekly_change",
                            "platform_specific.pinterest.monthly_change",
                            "platform_specific.pinterest.yearly_change"
                          ],
                          "categories": [],
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "country_code": "US",
                              "history": [],
                              "market_country_codes": [
                                "US"
                              ],
                              "monthly_change": 10,
                              "period_end_at": "2026-11-07T00:00:00Z",
                              "search_index": 71,
                              "seasonality": 0.98047054,
                              "weekly_change": -0.6,
                              "yearly_change": -0.02
                            }
                          },
                          "rank": 2,
                          "term": "pumpkin carving ideas",
                          "thumbnail_url": null,
                          "unknown_fields": [
                            "categories",
                            "platform_specific.pinterest.history"
                          ],
                          "url": "https://www.pinterest.com/search/pins/?q=pumpkin+carving+ideas"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.pinterest.weekly_change",
                            "platform_specific.pinterest.monthly_change",
                            "platform_specific.pinterest.yearly_change"
                          ],
                          "categories": [],
                          "platform": "pinterest",
                          "platform_specific": {
                            "pinterest": {
                              "country_code": "US",
                              "history": [],
                              "market_country_codes": [
                                "US"
                              ],
                              "monthly_change": 5,
                              "period_end_at": "2026-11-07T00:00:00Z",
                              "search_index": 54,
                              "seasonality": 0.9750034,
                              "weekly_change": -0.7,
                              "yearly_change": 0.3
                            }
                          },
                          "rank": 3,
                          "term": "pumpkin painting ideas",
                          "thumbnail_url": null,
                          "unknown_fields": [
                            "categories",
                            "platform_specific.pinterest.history"
                          ],
                          "url": "https://www.pinterest.com/search/pins/?q=pumpkin+painting+ideas"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "pinterest",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/PinterestTop_trendsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Top, rising and seasonal searches by country",
        "tags": [
          "Pinterest"
        ],
        "x-socialtap-endpoint": "pinterest.top_trends",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Pinterest Trends' rank for the board (1 = top)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "trend",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/pinterest/topic": {
      "get": {
        "description": "Returns a Pinterest ideas page (a topic) from its link or its words. You get its name, Pinterest's summary on category pages, and the related searches it suggests. You also get how many searches Pinterest counts for it, its followers, the broader topics above it, the narrower ones it offers, trending searches and the boards it shows. Words with no ideas page return not_found.\n\nReturns `{data, meta}`: `data` is a `Topic` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/pinterest/topic/ (Markdown: https://socialtap.dev/docs/reference/pinterest/topic/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/pinterest/topic/index.md)",
          "url": "https://socialtap.dev/docs/reference/pinterest/topic/"
        },
        "operationId": "pinterest.topic.get",
        "parameters": [
          {
            "description": "The topic: its ideas page link (pinterest.com/ideas/star-nail-designs/961385779129/, also on a country's site such as uk.pinterest.com or pinterest.co.uk) or its words (star nail designs). Words are matched as Pinterest matches them: case and hyphens are ignored.",
            "example": "https://www.pinterest.com/ideas/star-nail-designs/961385779129/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The topic: its ideas page link (pinterest.com/ideas/star-nail-designs/961385779129/, also on a country's site such as uk.pinterest.com or pinterest.co.uk) or its words (star nail designs). Words are matched as Pinterest matches them: case and hyphens are ignored.",
              "examples": [
                "https://www.pinterest.com/ideas/star-nail-designs/961385779129/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "description": null,
                        "id": "961385779129",
                        "name": "Star Nail Designs",
                        "platform": "pinterest",
                        "platform_specific": {
                          "pinterest": {
                            "cover_image_url": "https://i.pinimg.com/474x/37/81/19/378119e7f9eb391d50b55b175a04b870.jpg",
                            "follower_count": null,
                            "is_category": false,
                            "is_interest": false,
                            "parent_topics": [
                              {
                                "id": "935541271955",
                                "name": "Beauty",
                                "url": "https://www.pinterest.com/ideas/beauty/935541271955/"
                              },
                              {
                                "id": "956143059915",
                                "name": "Nails",
                                "url": "https://www.pinterest.com/ideas/nails/956143059915/"
                              },
                              {
                                "id": "944365099264",
                                "name": "Nail Art",
                                "url": "https://www.pinterest.com/ideas/nail-art/944365099264/"
                              }
                            ],
                            "refinements": [
                              {
                                "id": "920700149322",
                                "label": "Blue",
                                "name": "Blue Star Nail Designs",
                                "url": "https://www.pinterest.com/ideas/blue-star-nail-designs/920700149322/"
                              },
                              {
                                "id": "907171573460",
                                "label": "Moon",
                                "name": "Moon and Star Nail Designs",
                                "url": "https://www.pinterest.com/ideas/moon-and-star-nail-designs/907171573460/"
                              },
                              {
                                "id": "945556081760",
                                "label": "Black",
                                "name": "Black Star Nail Designs",
                                "url": "https://www.pinterest.com/ideas/black-star-nail-designs/945556081760/"
                              }
                            ],
                            "related_boards": [
                              {
                                "id": "1023513521504626611",
                                "title": "Nails",
                                "url": "https://www.pinterest.com/e18b0cb235799f1d10ec6bbc1873d1/nails/"
                              },
                              {
                                "id": "634866947410870831",
                                "title": "Nails",
                                "url": "https://www.pinterest.com/ngerceski/nails/"
                              },
                              {
                                "id": "396879854601657012",
                                "title": "nails",
                                "url": "https://www.pinterest.com/isabellagabriellagordon/nails/"
                              }
                            ],
                            "related_topics": [
                              {
                                "id": "949217630033",
                                "name": "Stars Nails Short",
                                "url": "https://www.pinterest.com/ideas/stars-nails-short/949217630033/"
                              },
                              {
                                "id": "960496442969",
                                "name": "Starry Nail Designs",
                                "url": "https://www.pinterest.com/ideas/starry-nail-designs/960496442969/"
                              },
                              {
                                "id": "945281507083",
                                "name": "Stars Nail Art",
                                "url": "https://www.pinterest.com/ideas/stars-nail-art/945281507083/"
                              }
                            ],
                            "search_count": 66701,
                            "trending_searches": [],
                            "updated_at": "2026-11-08T19:12:22Z"
                          }
                        },
                        "related_searches": [
                          "Blue Star Nail Designs",
                          "Moon and Star Nail Designs",
                          "Black Star Nail Designs"
                        ],
                        "unknown_fields": [],
                        "url": "https://www.pinterest.com/ideas/star-nail-designs/961385779129/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "pinterest",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "topic",
                          "id": "961385779129",
                          "url": "https://www.pinterest.com/ideas/star-nail-designs/961385779129/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/PinterestTopicResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Ideas page with related topics and search count",
        "tags": [
          "Pinterest"
        ],
        "x-socialtap-endpoint": "pinterest.topic",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "topic",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/pinterest/web_page": {
      "get": {
        "description": "Returns how many times a web page was saved to Pinterest, from the page's link. The count is exact, the number Pinterest's own Save button shows, for any page: an article, a recipe, a product, a video on another platform. A link no one saved, or a page that doesn't exist, counts zero.\n\nReturns `{data, meta}`: `data` is a `Web Page` object (the shared schema, the same on every platform). Null means unknown.\n\nIn Pinterest's words: `metrics.share_count` is saves.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/pinterest/web_page/ (Markdown: https://socialtap.dev/docs/reference/pinterest/web_page/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/pinterest/web_page/index.md)",
          "url": "https://socialtap.dev/docs/reference/pinterest/web_page/"
        },
        "operationId": "pinterest.web_page.get",
        "parameters": [
          {
            "description": "Any web page's link, exactly as people save it: an article, a recipe, a product page, another platform's video. Pinterest counts the exact string, so http and https, a trailing slash, a query string or a #fragment each count apart.",
            "example": "https://www.allrecipes.com/recipe/10813/best-chocolate-chip-cookies/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Any web page's link, exactly as people save it: an article, a recipe, a product page, another platform's video. Pinterest counts the exact string, so http and https, a trailing slash, a query string or a #fragment each count apart.",
              "examples": [
                "https://www.allrecipes.com/recipe/10813/best-chocolate-chip-cookies/"
              ],
              "format": "web_url",
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "metrics": {
                          "share_count": 35111
                        },
                        "platform": "pinterest",
                        "platform_specific": {},
                        "unknown_fields": [],
                        "url": "https://www.allrecipes.com/recipe/10813/best-chocolate-chip-cookies/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "pinterest",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "web",
                          "id": null,
                          "url": "https://www.allrecipes.com/recipe/10813/best-chocolate-chip-cookies/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/PinterestWeb_pageResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact Pinterest saves of any web page's link",
        "tags": [
          "Pinterest"
        ],
        "x-socialtap-endpoint": "pinterest.web_page",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "web_page",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/reddit/comments": {
      "get": {
        "description": "Returns the comments on a public Reddit post with their replies, in thread order and a page at a time, from the post's link or ID. Each has its text, author, posting and edit time, score (upvotes), depth and parent, awards, and whether it is by the post's author, pinned, a moderator's, collapsed or deleted. Sort by Reddit's own order, New, Old, Top, Controversial or Q&A. A comment's permalink returns that comment and its replies.\n\nReturns `{data, page, meta}`: `data` holds up to 200 `Comment` items (the shared schema, the same on every platform), Reddit's own order for the post (Best, or the order its moderators suggest), each comment followed by the replies Reddit shows with sort=relevance (the default), Reddit's Controversial order of comments (most evenly divided votes first), each followed by the replies Reddit shows with sort=controversial, Reddit's New order of comments (newest first), each followed by the replies Reddit shows with sort=newest, Reddit's Old order of comments (oldest first), each followed by the replies Reddit shows with sort=oldest, Reddit's Top order of comments (highest score first), each followed by the replies Reddit shows with sort=popular, Reddit's Q&A order (the comments the post's author answered first), each followed by the replies Reddit shows with sort=qa. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Reddit's words: `metrics.like_count` is upvotes (score).\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/reddit/comments/ (Markdown: https://socialtap.dev/docs/reference/reddit/comments/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/reddit/comments/index.md)",
          "url": "https://socialtap.dev/docs/reference/reddit/comments/"
        },
        "operationId": "reddit.comments.list",
        "parameters": [
          {
            "description": "Reddit post URL: a post's page on any reddit.com host (www, old, new, np, m, sh), with or without its subreddit or slug, a /gallery/ link, a redd.it short link, an app share link (/r/<subreddit>/s/<code>), a v.redd.it video link, or the post's ID (t3_ prefix optional). A comment's permalink (/comments/<id>/comment/<comment id>/) lists that comment and its replies instead of the whole post.",
            "example": "https://www.reddit.com/r/IAmA/comments/z1c9z/i_am_barack_obama_president_of_the_united_states/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Reddit post URL: a post's page on any reddit.com host (www, old, new, np, m, sh), with or without its subreddit or slug, a /gallery/ link, a redd.it short link, an app share link (/r/<subreddit>/s/<code>), a v.redd.it video link, or the post's ID (t3_ prefix optional). A comment's permalink (/comments/<id>/comment/<comment id>/) lists that comment and its replies instead of the whole post.",
              "examples": [
                "https://www.reddit.com/r/IAmA/comments/z1c9z/i_am_barack_obama_president_of_the_united_states/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. relevance (default): Reddit's own order for the post, Best unless its moderators suggest another (many AMAs use Q&A). newest: New. oldest: Old. popular: Top. controversial: Controversial (the most evenly divided votes first). qa: Q&A (the comments the post's author answered first, with the answers). Each comment is followed by the replies Reddit shows under it.",
            "example": "relevance",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "relevance",
              "description": "Order of the results. relevance (default): Reddit's own order for the post, Best unless its moderators suggest another (many AMAs use Q&A). newest: New. oldest: Old. popular: Top. controversial: Controversial (the most evenly divided votes first). qa: Q&A (the comments the post's author answered first, with the answers). Each comment is followed by the replies Reddit shows under it.",
              "enum": [
                "relevance",
                "newest",
                "oldest",
                "popular",
                "controversial",
                "qa"
              ],
              "type": "string"
            }
          },
          {
            "description": "all (default): a walk returns the whole tree, every reply Reddit left behind a \"more replies\" link included (on the pages after the one that shows its parent). shown: only the post's comments with the replies Reddit shows under them; each comment's platform_specific.reddit.more_replies_count counts the rest and its url lists them. A permalink's walk follows the same rule under its comment.",
            "example": "shown",
            "in": "query",
            "name": "replies",
            "schema": {
              "default": "all",
              "description": "all (default): a walk returns the whole tree, every reply Reddit left behind a \"more replies\" link included (on the pages after the one that shows its parent). shown: only the post's comments with the replies Reddit shows under them; each comment's platform_specific.reddit.more_replies_count counts the rest and its url lists them. A permalink's walk follows the same rule under its comment.",
              "enum": [
                "all",
                "shown"
              ],
              "examples": [
                "shown"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at. Comments come in thread order, not by time: since and until filter the comments of each page, and the walk goes on past them.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at. Comments come in thread order, not by time: since and until filter the comments of each page, and the walk goes on past them.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 200,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 200,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://www.redditstatic.com/avatars/defaults/v2/avatar_default_3.png",
                            "display_name": null,
                            "id": "t2_60d4r",
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/gobearss/",
                            "username": "gobearss"
                          },
                          "edited_at": null,
                          "id": "t1_c60mmaf",
                          "is_by_post_author": false,
                          "is_edited": false,
                          "is_liked_by_author": null,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": 1556,
                            "reply_count": null
                          },
                          "parent_id": null,
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": null,
                              "depth": 0,
                              "distinguished": null,
                              "is_collapsed": false,
                              "is_deleted": false,
                              "more_replies_count": 8,
                              "post": null,
                              "reply_to_author": null,
                              "score": 1556,
                              "subreddit": {
                                "id": "t5_2qzb6",
                                "name": "IAmA",
                                "url": "https://www.reddit.com/r/IAmA/"
                              }
                            }
                          },
                          "post_id": "t3_z1c9z",
                          "published_at": "2012-08-29T20:05:19Z",
                          "text": "How do you balance family life and hobbies with, well, being the POTUS?",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/r/IAmA/comments/z1c9z/comment/c60mmaf/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://www.redditstatic.com/avatars/defaults/v2/avatar_default_2.png",
                            "display_name": null,
                            "id": "t2_8t1cq",
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/PresidentObama/",
                            "username": "PresidentObama"
                          },
                          "edited_at": null,
                          "id": "t1_c60nmtc",
                          "is_by_post_author": true,
                          "is_edited": false,
                          "is_liked_by_author": null,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": 2951,
                            "reply_count": null
                          },
                          "parent_id": "t1_c60mmaf",
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": null,
                              "depth": 1,
                              "distinguished": null,
                              "is_collapsed": false,
                              "is_deleted": false,
                              "more_replies_count": 285,
                              "post": null,
                              "reply_to_author": null,
                              "score": 2951,
                              "subreddit": {
                                "id": "t5_2qzb6",
                                "name": "IAmA",
                                "url": "https://www.reddit.com/r/IAmA/"
                              }
                            }
                          },
                          "post_id": "t3_z1c9z",
                          "published_at": "2012-08-29T21:04:58Z",
                          "text": "It's hard - truthfully the main thing other than work is just making sure that I'm spending enough time with michelle and the girls. The big advantage I have is that I live above the store - so I have no commute! So we make sure that when I'm in DC I never miss dinner with them a…",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/r/IAmA/comments/z1c9z/comment/c60nmtc/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": null,
                            "display_name": "[deleted]",
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "edited_at": null,
                          "id": "t1_c60npsu",
                          "is_by_post_author": null,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": null,
                            "reply_count": null
                          },
                          "parent_id": "t1_c60nmtc",
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": null,
                              "depth": 2,
                              "distinguished": null,
                              "is_collapsed": false,
                              "is_deleted": true,
                              "more_replies_count": 33,
                              "post": null,
                              "reply_to_author": null,
                              "score": null,
                              "subreddit": {
                                "id": "t5_2qzb6",
                                "name": "IAmA",
                                "url": "https://www.reddit.com/r/IAmA/"
                              }
                            }
                          },
                          "post_id": "t3_z1c9z",
                          "published_at": "2012-08-29T21:11:23Z",
                          "text": "",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/comments/z1c9z/comment/c60npsu/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "reddit",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 667,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "t3_z1c9z",
                          "url": "https://www.reddit.com/comments/z1c9z/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RedditCommentsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Post comments and replies, in thread order",
        "tags": [
          "Reddit"
        ],
        "x-socialtap-endpoint": "reddit.comments",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Reddit's own order for the post (Best, or the order its moderators suggest), each comment followed by the replies Reddit shows",
          "orders": {
            "controversial": "Reddit's Controversial order of comments (most evenly divided votes first), each followed by the replies Reddit shows",
            "newest": "Reddit's New order of comments (newest first), each followed by the replies Reddit shows",
            "oldest": "Reddit's Old order of comments (oldest first), each followed by the replies Reddit shows",
            "popular": "Reddit's Top order of comments (highest score first), each followed by the replies Reddit shows",
            "qa": "Reddit's Q&A order (the comments the post's author answered first), each followed by the replies Reddit shows",
            "relevance": "Reddit's own order for the post (Best, or the order its moderators suggest), each comment followed by the replies Reddit shows"
          },
          "page_max": 200,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/reddit/engagement": {
      "get": {
        "description": "Returns a public Reddit user's profile and latest posts, with upvotes and comments per post, posting cadence and top posts computed over them. It also has the comment-to-upvote ratio, the mix of text, link, image and video posts, the bottom post, and how each post compares with the user's typical post. Engagement rates are null, because Reddit shows no follower or view counts. One request, from a username or profile link.\n\nReturns `{data, meta}`: `data` is a `Engagement` object (the shared schema, the same on every platform). Null means unknown.\n\nIn Reddit's words: `metrics.comment_to_like_ratio` is comment-to-upvote ratio, `metrics.likes_per_post` is upvotes (score) per post, `posts[].post.metrics.like_count` is upvotes (score).\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/reddit/engagement/ (Markdown: https://socialtap.dev/docs/reference/reddit/engagement/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/reddit/engagement/index.md)",
          "url": "https://socialtap.dev/docs/reference/reddit/engagement/"
        },
        "operationId": "reddit.engagement.get",
        "parameters": [
          {
            "description": "Reddit username, with or without u/ (spez, u/spez, /u/spez), or a profile link on any reddit.com host (www, old, new, np, m: reddit.com/user/spez, reddit.com/u/spez, with a tab such as /submitted or /comments), or the user's profile subreddit (reddit.com/r/u_spez). Usernames are case-insensitive. A t2_ account ID is refused: Reddit's public pages look users up by name only.",
            "example": "GallowBoob",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Reddit username, with or without u/ (spez, u/spez, /u/spez), or a profile link on any reddit.com host (www, old, new, np, m: reddit.com/user/spez, reddit.com/u/spez, with a tab such as /submitted or /comments), or the user's profile subreddit (reddit.com/r/u_spez). Usernames are case-insensitive. A t2_ account ID is refused: Reddit's public pages look users up by name only.",
              "examples": [
                "GallowBoob"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "bottom_post_id": "t3_1m2sh2k",
                        "id": "t2_iqsg6",
                        "metrics": {
                          "comment_to_like_ratio": 0.044405,
                          "comments_per_post": 99.88,
                          "counted_post_count": 24,
                          "engagement_rate": null,
                          "engagement_rate_stddev": null,
                          "formats": [
                            {
                              "counted_post_count": 15,
                              "engagement_rate": null,
                              "interactions_per_post": 3098.47,
                              "type": "image",
                              "views_per_post": null
                            },
                            {
                              "counted_post_count": 8,
                              "engagement_rate": null,
                              "interactions_per_post": 1212.63,
                              "type": "video",
                              "views_per_post": null
                            },
                            {
                              "counted_post_count": 1,
                              "engagement_rate": null,
                              "interactions_per_post": 200,
                              "type": "carousel",
                              "views_per_post": null
                            }
                          ],
                          "interactions_per_post": 2349.08,
                          "likes_per_post": 2249.21,
                          "median_engagement_rate": null,
                          "median_views_per_post": null,
                          "posts_per_week": 0.11,
                          "quotes_per_post": null,
                          "rated_post_count": 24,
                          "reposts_per_post": null,
                          "sampled_post_count": 25,
                          "saves_per_post": null,
                          "shares_per_post": null,
                          "view_engagement_rate": null,
                          "views_per_post": null
                        },
                        "newest_post_at": "2026-10-09T16:14:29Z",
                        "oldest_post_at": "2022-12-09T02:55:52Z",
                        "platform": "reddit",
                        "platform_specific": {},
                        "posts": [
                          {
                            "engagement_rate": null,
                            "engagement_vs_median": 33.33,
                            "is_counted": false,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": "https://styles.redditmedia.com/t5_3kl0d/styles/profileIcon_c4zmya3oel6h1.png?width=48&height=48&frame=1&auto=webp&crop=48%3A48%2Csmart&s=d4c3218b2ab8994e02e897782f5c6522d0c0d47e",
                                "display_name": null,
                                "id": "t2_iqsg6",
                                "is_verified": null,
                                "url": "https://www.reddit.com/user/GallowBoob/",
                                "username": "GallowBoob"
                              },
                              "coauthors": [],
                              "duration_ms": null,
                              "hashtags": [],
                              "id": "t3_fgghrs",
                              "is_nsfw": false,
                              "is_pinned": true,
                              "is_sponsored": false,
                              "language": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": null,
                                  "height": null,
                                  "thumbnail_url": null,
                                  "type": "image",
                                  "url": "https://i.redd.it/41i4qishgvl41.jpg",
                                  "width": null
                                }
                              ],
                              "mentions": [],
                              "metrics": {
                                "comment_count": 66,
                                "like_count": 7949,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": null,
                                "share_count": null,
                                "view_count": null
                              },
                              "platform": "reddit",
                              "platform_specific": {
                                "reddit": {
                                  "award_count": null,
                                  "crosspost_of": null,
                                  "domain": "i.redd.it",
                                  "flair": null,
                                  "is_archived": false,
                                  "is_locked": true,
                                  "is_spoiler": false,
                                  "link_url": null,
                                  "score": 7949,
                                  "subreddit": {
                                    "id": "t5_3kl0d",
                                    "name": "u_GallowBoob",
                                    "url": "https://www.reddit.com/r/u_GallowBoob/"
                                  },
                                  "upvote_ratio": 0.9687462863933453
                                }
                              },
                              "platform_type": "image",
                              "published_at": "2020-03-10T16:27:45Z",
                              "text": null,
                              "thumbnail_url": "https://i.redd.it/41i4qishgvl41.jpg",
                              "title": "‪Everything in balance.‬ ‪Except karma ⬆️‬⬆️⬆️",
                              "type": "image",
                              "unknown_fields": [],
                              "url": "https://www.reddit.com/user/GallowBoob/comments/fgghrs/everything_in_balance_except_karma/"
                            },
                            "view_engagement_rate": null,
                            "views_vs_median": null
                          },
                          {
                            "engagement_rate": null,
                            "engagement_vs_median": 1.07,
                            "is_counted": true,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": "https://styles.redditmedia.com/t5_3kl0d/styles/profileIcon_c4zmya3oel6h1.png?width=64&height=64&frame=1&auto=webp&crop=64%3A64%2Csmart&s=622fbbf4e9da2b328d998f838980358e9848839b",
                                "display_name": null,
                                "id": "t2_iqsg6",
                                "is_verified": null,
                                "url": "https://www.reddit.com/user/GallowBoob/",
                                "username": "GallowBoob"
                              },
                              "coauthors": [],
                              "duration_ms": null,
                              "hashtags": [],
                              "id": "t3_1x1pjzw",
                              "is_nsfw": false,
                              "is_pinned": false,
                              "is_sponsored": false,
                              "language": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": null,
                                  "height": null,
                                  "thumbnail_url": null,
                                  "type": "image",
                                  "url": "https://i.redd.it/tbq8zdb1vguh1.jpeg",
                                  "width": null
                                }
                              ],
                              "mentions": [],
                              "metrics": {
                                "comment_count": 15,
                                "like_count": 242,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": null,
                                "share_count": null,
                                "view_count": null
                              },
                              "platform": "reddit",
                              "platform_specific": {
                                "reddit": {
                                  "award_count": 0,
                                  "crosspost_of": null,
                                  "domain": "i.redd.it",
                                  "flair": null,
                                  "is_archived": false,
                                  "is_locked": false,
                                  "is_spoiler": false,
                                  "link_url": null,
                                  "score": 242,
                                  "subreddit": {
                                    "id": "t5_2qh1o",
                                    "name": "aww",
                                    "url": "https://www.reddit.com/r/aww/"
                                  },
                                  "upvote_ratio": 0.9801587301587301
                                }
                              },
                              "platform_type": "image",
                              "published_at": "2026-10-09T16:14:29Z",
                              "text": null,
                              "thumbnail_url": "https://i.redd.it/tbq8zdb1vguh1.jpeg",
                              "title": "She’s 2 years old! 🎉",
                              "type": "image",
                              "unknown_fields": [],
                              "url": "https://www.reddit.com/r/aww/comments/1x1pjzw/shes_2_years_old/"
                            },
                            "view_engagement_rate": null,
                            "views_vs_median": null
                          },
                          {
                            "engagement_rate": null,
                            "engagement_vs_median": 0.33,
                            "is_counted": true,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": "https://styles.redditmedia.com/t5_3kl0d/styles/profileIcon_c4zmya3oel6h1.png?width=64&height=64&frame=1&auto=webp&crop=64%3A64%2Csmart&s=622fbbf4e9da2b328d998f838980358e9848839b",
                                "display_name": null,
                                "id": "t2_iqsg6",
                                "is_verified": null,
                                "url": "https://www.reddit.com/user/GallowBoob/",
                                "username": "GallowBoob"
                              },
                              "coauthors": [],
                              "duration_ms": 40000,
                              "hashtags": [],
                              "id": "t3_1uz79k3",
                              "is_nsfw": false,
                              "is_pinned": false,
                              "is_sponsored": false,
                              "language": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": 40000,
                                  "expires_at": "2026-11-03T01:00:00Z",
                                  "height": 1920,
                                  "thumbnail_url": "https://external-preview.redd.it/shes-enjoying-the-summer-breeze-v0-NG4wNjBpcnV4dGRoMdQqmHkdc8VnKxXpXRKk_w_FM2SWI08gkBzSPUTOCnDs.png?width=640&crop=smart&format=pjpg&auto=webp&s=852591d0e96218504c059b335546bb9a5719cfdd",
                                  "type": "video",
                                  "url": "https://packaged-media.redd.it/8u59jcvuxtdh1/pb/m2-res_1920p.mp4?m=DASHPlaylist.mpd&var=sgpssan&v=1&e=1793667600&s=4618cb794fbb1602a0442b562fb1609f2b60c096",
                                  "width": 1080
                                }
                              ],
                              "mentions": [],
                              "metrics": {
                                "comment_count": 10,
                                "like_count": 69,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": null,
                                "share_count": null,
                                "view_count": null
                              },
                              "platform": "reddit",
                              "platform_specific": {
                                "reddit": {
                                  "award_count": 0,
                                  "crosspost_of": null,
                                  "domain": "v.redd.it",
                                  "flair": null,
                                  "is_archived": false,
                                  "is_locked": false,
                                  "is_spoiler": false,
                                  "link_url": null,
                                  "score": 69,
                                  "subreddit": {
                                    "id": "t5_2qh1o",
                                    "name": "aww",
                                    "url": "https://www.reddit.com/r/aww/"
                                  },
                                  "upvote_ratio": 0.9722222222222222
                                }
                              },
                              "platform_type": "video",
                              "published_at": "2026-07-17T18:03:16Z",
                              "text": null,
                              "thumbnail_url": "https://external-preview.redd.it/shes-enjoying-the-summer-breeze-v0-NG4wNjBpcnV4dGRoMdQqmHkdc8VnKxXpXRKk_w_FM2SWI08gkBzSPUTOCnDs.png?width=640&crop=smart&format=pjpg&auto=webp&s=852591d0e96218504c059b335546bb9a5719cfdd",
                              "title": "She’s enjoying the summer breeze [OC]",
                              "type": "video",
                              "unknown_fields": [],
                              "url": "https://www.reddit.com/r/aww/comments/1uz79k3/shes_enjoying_the_summer_breeze_oc/"
                            },
                            "view_engagement_rate": null,
                            "views_vs_median": null
                          }
                        ],
                        "profile": {
                          "approximate_fields": [
                            "created_at",
                            "platform_specific.reddit.moderated_subreddits"
                          ],
                          "avatar_url": "https://styles.redditmedia.com/t5_3kl0d/styles/profileIcon_c4zmya3oel6h1.png",
                          "banner_url": "https://styles.redditmedia.com/t5_3kl0d/styles/profileBanner_74ugoeyr5nif1.png",
                          "bio": "The internet was a mistake 🌍 Always remember the human.",
                          "category": null,
                          "country_code": null,
                          "created_at": "2014-10-07T00:00:00Z",
                          "display_name": "Rob",
                          "external_links": [
                            {
                              "title": "thegallowboob",
                              "url": "https://twitter.com/thegallowboob"
                            }
                          ],
                          "id": "t2_iqsg6",
                          "is_private": false,
                          "is_verified": false,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "comment_karma": 1110838,
                              "contribution_count": 27374,
                              "is_admin": false,
                              "is_nsfw": false,
                              "is_premium": true,
                              "karma": 36838255,
                              "moderated_subreddits": [
                                {
                                  "id": "t5_2x93b",
                                  "name": "oddlysatisfying",
                                  "url": "https://www.reddit.com/r/oddlysatisfying/"
                                },
                                {
                                  "id": "t5_m0bnr",
                                  "name": "nextfuckinglevel",
                                  "url": "https://www.reddit.com/r/nextfuckinglevel/"
                                },
                                {
                                  "id": "t5_37xo2",
                                  "name": "RoastMe",
                                  "url": "https://www.reddit.com/r/RoastMe/"
                                }
                              ],
                              "post_karma": 35727417,
                              "trophies": [
                                {
                                  "description": null,
                                  "granted_at": null,
                                  "image_url": "https://i.redd.it/cms/1a51152004126674_trophy_image_for_12_year_club.png",
                                  "name": "12-Year Club",
                                  "url": null
                                },
                                {
                                  "description": null,
                                  "granted_at": "2023-01-01T00:00:00Z",
                                  "image_url": "https://i.redd.it/cms/0ff4a7db3bca21f7_trophy_image_for_wellrounded.png",
                                  "name": "Well-Rounded",
                                  "url": null
                                },
                                {
                                  "description": null,
                                  "granted_at": "2023-01-01T00:00:00Z",
                                  "image_url": "https://i.redd.it/cms/0ff4a7db3bca21f7_trophy_image_for_wellrounded.png",
                                  "name": "Well-Rounded",
                                  "url": null
                                }
                              ]
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/user/GallowBoob/",
                          "username": "GallowBoob"
                        },
                        "top_post_id": "t3_16y770f",
                        "unknown_fields": [],
                        "url": "https://www.reddit.com/user/GallowBoob/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "reddit",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1677,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "t2_iqsg6",
                          "url": "https://www.reddit.com/user/GallowBoob/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RedditEngagementResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Upvotes per post, posting cadence and top posts",
        "tags": [
          "Reddit"
        ],
        "x-socialtap-endpoint": "reddit.engagement",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "engagement",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/reddit/post": {
      "get": {
        "description": "Returns a public Reddit post from its link, share link or ID: title, text, author, subreddit, score (upvotes), upvote ratio and comment count. It also has every image of a gallery or the video with its length, the linked page of a link post, the award count, the flair, and whether the post is NSFW, a spoiler, locked, archived or a crosspost. Comment permalinks, redd.it and v.redd.it links work too.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\nIn Reddit's words: `metrics.like_count` is upvotes (score).\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/reddit/post/ (Markdown: https://socialtap.dev/docs/reference/reddit/post/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/reddit/post/index.md)",
          "url": "https://socialtap.dev/docs/reference/reddit/post/"
        },
        "operationId": "reddit.post.get",
        "parameters": [
          {
            "description": "Reddit post URL: a post's page on any reddit.com host (www, old, new, np, m, sh), with or without its subreddit or slug, a comment's permalink (its post is returned), a /gallery/ link, a redd.it short link, an app share link (/r/<subreddit>/s/<code>), a v.redd.it video link, or the post's ID (t3_ prefix optional).",
            "example": "https://www.reddit.com/r/IAmA/comments/z1c9z/i_am_barack_obama_president_of_the_united_states/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Reddit post URL: a post's page on any reddit.com host (www, old, new, np, m, sh), with or without its subreddit or slug, a comment's permalink (its post is returned), a /gallery/ link, a redd.it short link, an app share link (/r/<subreddit>/s/<code>), a v.redd.it video link, or the post's ID (t3_ prefix optional).",
              "examples": [
                "https://www.reddit.com/r/IAmA/comments/z1c9z/i_am_barack_obama_president_of_the_united_states/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://www.redditstatic.com/avatars/defaults/v2/avatar_default_2.png",
                          "display_name": null,
                          "id": "t2_8t1cq",
                          "is_verified": null,
                          "url": "https://www.reddit.com/user/PresidentObama/",
                          "username": "PresidentObama"
                        },
                        "coauthors": [],
                        "duration_ms": null,
                        "hashtags": [],
                        "id": "t3_z1c9z",
                        "is_nsfw": false,
                        "is_pinned": null,
                        "is_sponsored": false,
                        "language": "en",
                        "media": [],
                        "mentions": [],
                        "metrics": {
                          "comment_count": 22716,
                          "like_count": 216186,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": null,
                          "share_count": null,
                          "view_count": null
                        },
                        "platform": "reddit",
                        "platform_specific": {
                          "reddit": {
                            "award_count": 0,
                            "crosspost_of": null,
                            "domain": "self.IAmA",
                            "flair": null,
                            "is_archived": true,
                            "is_locked": false,
                            "is_spoiler": false,
                            "link_url": null,
                            "score": 216186,
                            "subreddit": {
                              "id": "t5_2qzb6",
                              "name": "IAmA",
                              "url": "https://www.reddit.com/r/IAmA/"
                            },
                            "upvote_ratio": 0.8218045766988602
                          }
                        },
                        "platform_type": "multi_media",
                        "published_at": "2012-08-29T20:01:36Z",
                        "text": "Hi, I’m Barack Obama, President of the United States. Ask me anything. I’ll be taking your questions for half an hour starting at about 4:30 ET.\n\nProof it's me: https://twitter.com/BarackObama/status/240903767350968320\n\nWe're running early and will get started soon.\n\nUPDATE: Hey …",
                        "thumbnail_url": null,
                        "title": "I am Barack Obama, President of the United States -- AMA",
                        "type": "text",
                        "unknown_fields": [],
                        "url": "https://www.reddit.com/r/IAmA/comments/z1c9z/i_am_barack_obama_president_of_the_united_states/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "reddit",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 980,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "t3_z1c9z",
                          "url": "https://www.reddit.com/r/IAmA/comments/z1c9z/i_am_barack_obama_president_of_the_united_states/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RedditPostResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Upvotes, comment count, media and flair",
        "tags": [
          "Reddit"
        ],
        "x-socialtap-endpoint": "reddit.post",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/reddit/posts": {
      "get": {
        "description": "Returns the public posts a Reddit user submitted, a page at a time, from their username or profile link. Each has its title, text, subreddit, score, upvote ratio, comment and award counts, flair, images, gallery or video, and whether it is pinned to the profile, NSFW, a spoiler, locked or archived. Sort by New, Top, Hot or Controversial, and set since to stop at a date.\n\nReturns `{data, page, meta}`: `data` holds up to 25 `Post` items (the shared schema, the same on every platform), newest first with sort=newest (the default), Reddit's Controversial order (most evenly divided votes first), of all time or of the time filter that covers since with sort=controversial, Reddit's Top order (highest score first), of all time or of the time filter that covers since with sort=popular, Reddit's Hot order (recent posts ranked by their votes) with sort=relevance. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Reddit's words: `metrics.like_count` is upvotes (score).\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/reddit/posts/ (Markdown: https://socialtap.dev/docs/reference/reddit/posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/reddit/posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/reddit/posts/"
        },
        "operationId": "reddit.posts.list",
        "parameters": [
          {
            "description": "Reddit username, with or without u/ (spez, u/spez, /u/spez), or a profile link on any reddit.com host (www, old, new, np, m: reddit.com/user/spez, reddit.com/u/spez, with a tab such as /submitted or /comments), or the user's profile subreddit (reddit.com/r/u_spez). Usernames are case-insensitive. A t2_ account ID is refused: Reddit's public pages look users up by name only.",
            "example": "https://www.reddit.com/user/spez/",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Reddit username, with or without u/ (spez, u/spez, /u/spez), or a profile link on any reddit.com host (www, old, new, np, m: reddit.com/user/spez, reddit.com/u/spez, with a tab such as /submitted or /comments), or the user's profile subreddit (reddit.com/r/u_spez). Usernames are case-insensitive. A t2_ account ID is refused: Reddit's public pages look users up by name only.",
              "examples": [
                "spez"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. newest (default): New, newest first. popular: Top, highest score first (of all time, or of the narrowest of Reddit's past hour, day, week, month or year that covers since). relevance: Hot, Reddit's ranking of recent posts by their votes. controversial: Controversial, the most evenly divided votes first (in the same time filter as popular). Posts pinned to the profile come first on each. A link's tab or sort does not set it.",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "newest",
              "description": "Order of the results. newest (default): New, newest first. popular: Top, highest score first (of all time, or of the narrowest of Reddit's past hour, day, week, month or year that covers since). relevance: Hot, Reddit's ranking of recent posts by their votes. controversial: Controversial, the most evenly divided votes first (in the same time filter as popular). Posts pinned to the profile come first on each. A link's tab or sort does not set it.",
              "enum": [
                "newest",
                "popular",
                "relevance",
                "controversial"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at. On newest the walk stops at the first older post; on popular and controversial Reddit's own time filter that covers since is applied, so fewer pages are fetched, and every page is filtered exactly.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at. On newest the walk stops at the first older post; on popular and controversial Reddit's own time filter that covers since is applied, so fewer pages are fetched, and every page is filtered exactly.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 25,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 25,
              "maximum": 25,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://styles.redditmedia.com/t5_3k30p/styles/profileIcon_uj015iwx9s7g1.png?width=48&height=48&frame=1&auto=webp&crop=48%3A48%2Csmart&s=f4940ed370a17a813fda1db1cdefc8d12b3a53a7",
                            "display_name": null,
                            "id": "t2_1w72",
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/spez/",
                            "username": "spez"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "t3_1xiupm0",
                          "is_nsfw": false,
                          "is_pinned": false,
                          "is_sponsored": false,
                          "language": null,
                          "media": [],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 478,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": 10,
                              "crosspost_of": null,
                              "domain": "self.spez",
                              "flair": null,
                              "is_archived": false,
                              "is_locked": false,
                              "is_spoiler": false,
                              "link_url": null,
                              "score": null,
                              "subreddit": {
                                "id": "t5_3k30p",
                                "name": "u_spez",
                                "url": "https://www.reddit.com/r/u_spez/"
                              },
                              "upvote_ratio": 0.26542056074766357
                            }
                          },
                          "platform_type": "text",
                          "published_at": "2026-10-29T20:08:37Z",
                          "text": "I want to talk about a big change we're making on Reddit: we're going to evolve Reddit to being a primarily logged-in experience.\n\nThis is a big change for Reddit, where we've allowed logged-out access to basically all of Reddit for the last two decades. And I don’t know about yo…",
                          "thumbnail_url": null,
                          "title": "About that login screen",
                          "type": "text",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/user/spez/comments/1xiupm0/about_that_login_screen/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://styles.redditmedia.com/t5_3k30p/styles/profileIcon_uj015iwx9s7g1.png?width=48&height=48&frame=1&auto=webp&crop=48%3A48%2Csmart&s=f4940ed370a17a813fda1db1cdefc8d12b3a53a7",
                            "display_name": null,
                            "id": "t2_1w72",
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/spez/",
                            "username": "spez"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "t3_1vgbkge",
                          "is_nsfw": false,
                          "is_pinned": false,
                          "is_sponsored": false,
                          "language": null,
                          "media": [],
                          "mentions": [
                            "keysersosa",
                            "Go_JasonWaterfalls",
                            "spez"
                          ],
                          "metrics": {
                            "comment_count": 491,
                            "like_count": 371,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": 2,
                              "crosspost_of": null,
                              "domain": "self.spez",
                              "flair": null,
                              "is_archived": false,
                              "is_locked": false,
                              "is_spoiler": false,
                              "link_url": null,
                              "score": 371,
                              "subreddit": {
                                "id": "t5_3k30p",
                                "name": "u_spez",
                                "url": "https://www.reddit.com/r/u_spez/"
                              },
                              "upvote_ratio": 0.8480300187617261
                            }
                          },
                          "platform_type": "multi_media",
                          "published_at": "2026-08-05T16:03:56Z",
                          "text": "Hi everyone,\n\nLast May, I shared how we were building Reddit for its next chapter. I owe you an update, including a few changes I know some people will have strong opinions about.\n\nWhile we’ve made upgrades to the platform over the last 21 years, we need to continually evolve to …",
                          "thumbnail_url": null,
                          "title": "Modernizing Reddit’s infrastructure with you",
                          "type": "text",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/user/spez/comments/1vgbkge/modernizing_reddits_infrastructure_with_you/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://styles.redditmedia.com/t5_3k30p/styles/profileIcon_uj015iwx9s7g1.png?width=48&height=48&frame=1&auto=webp&crop=48%3A48%2Csmart&s=f4940ed370a17a813fda1db1cdefc8d12b3a53a7",
                            "display_name": null,
                            "id": "t2_1w72",
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/spez/",
                            "username": "spez"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "t3_1u7hraf",
                          "is_nsfw": false,
                          "is_pinned": false,
                          "is_sponsored": false,
                          "language": null,
                          "media": [],
                          "mentions": [
                            "spez"
                          ],
                          "metrics": {
                            "comment_count": 310,
                            "like_count": 942,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": 28,
                              "crosspost_of": null,
                              "domain": "self.spez",
                              "flair": null,
                              "is_archived": false,
                              "is_locked": false,
                              "is_spoiler": false,
                              "link_url": null,
                              "score": 942,
                              "subreddit": {
                                "id": "t5_3k30p",
                                "name": "u_spez",
                                "url": "https://www.reddit.com/r/u_spez/"
                              },
                              "upvote_ratio": 0.914612676056338
                            }
                          },
                          "platform_type": "multi_media",
                          "published_at": "2026-06-16T16:04:27Z",
                          "text": "Hi everyone,\n\nReddit turns 21 next week. Funny enough, it’s the same age I was when we started it. Save your jokes about r/13or30, I’ve already heard them.\n\nThat’s a long time in human years and an even longer time in internet years.\n\nWhen a few of us started Reddit back in 2005,…",
                          "thumbnail_url": null,
                          "title": "21 years of Reddit",
                          "type": "text",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/user/spez/comments/1u7hraf/21_years_of_reddit/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "reddit",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 676,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "t2_1w72",
                          "url": "https://www.reddit.com/user/spez/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "end"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RedditPostsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Submissions sorted New, Top or Hot, with scores",
        "tags": [
          "Reddit"
        ],
        "x-socialtap-endpoint": "reddit.posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "orders": {
            "controversial": "Reddit's Controversial order (most evenly divided votes first), of all time or of the time filter that covers since",
            "newest": "newest first",
            "popular": "Reddit's Top order (highest score first), of all time or of the time filter that covers since",
            "relevance": "Reddit's Hot order (recent posts ranked by their votes)"
          },
          "page_max": 25,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/reddit/profile": {
      "get": {
        "description": "Returns a public Reddit user from their username or profile link: post, comment and total karma, cake day, avatar, banner and description. It also has the t2_ account ID, whether the account is verified, a Reddit admin, Premium or marked NSFW, its social links, the subreddits it moderates and its trophy case.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/reddit/profile/ (Markdown: https://socialtap.dev/docs/reference/reddit/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/reddit/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/reddit/profile/"
        },
        "operationId": "reddit.profile.get",
        "parameters": [
          {
            "description": "Reddit username, with or without u/ (spez, u/spez, /u/spez), or a profile link on any reddit.com host (www, old, new, np, m: reddit.com/user/spez, reddit.com/u/spez, with a tab such as /submitted or /comments), or the user's profile subreddit (reddit.com/r/u_spez). Usernames are case-insensitive. A t2_ account ID is refused: Reddit's public pages look users up by name only.",
            "example": "https://www.reddit.com/user/spez/",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Reddit username, with or without u/ (spez, u/spez, /u/spez), or a profile link on any reddit.com host (www, old, new, np, m: reddit.com/user/spez, reddit.com/u/spez, with a tab such as /submitted or /comments), or the user's profile subreddit (reddit.com/r/u_spez). Usernames are case-insensitive. A t2_ account ID is refused: Reddit's public pages look users up by name only.",
              "examples": [
                "spez"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "created_at",
                          "platform_specific.reddit.moderated_subreddits"
                        ],
                        "avatar_url": "https://styles.redditmedia.com/t5_3k30p/styles/profileIcon_uj015iwx9s7g1.png",
                        "banner_url": null,
                        "bio": "Reddit CEO",
                        "category": null,
                        "country_code": null,
                        "created_at": "2005-06-06T00:00:00Z",
                        "display_name": "spez",
                        "external_links": [],
                        "id": "t2_1w72",
                        "is_private": false,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": null,
                          "following_count": null,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "reddit",
                        "platform_specific": {
                          "reddit": {
                            "comment_karma": 756623,
                            "contribution_count": 4079,
                            "is_admin": true,
                            "is_nsfw": false,
                            "is_premium": true,
                            "karma": 941387,
                            "moderated_subreddits": [
                              {
                                "id": "t5_2r0ij",
                                "name": "announcements",
                                "url": "https://www.reddit.com/r/announcements/"
                              },
                              {
                                "id": "t5_2qh49",
                                "name": "blog",
                                "url": "https://www.reddit.com/r/blog/"
                              },
                              {
                                "id": "t5_2fwo",
                                "name": "programming",
                                "url": "https://www.reddit.com/r/programming/"
                              }
                            ],
                            "post_karma": 184764,
                            "trophies": [
                              {
                                "description": null,
                                "granted_at": null,
                                "image_url": "https://i.redd.it/cms/871b9df322b7cddd_trophy_image_for_20_year_club.png",
                                "name": "20-Year Club",
                                "url": null
                              },
                              {
                                "description": null,
                                "granted_at": null,
                                "image_url": "https://i.redd.it/cms/034d06bbd23e0a6d_trophy_image_for_verified_email.png",
                                "name": "Verified Email",
                                "url": null
                              },
                              {
                                "description": "Unlocked by completing the online mod course, \"Mod 101: Moderator Certification\".",
                                "granted_at": null,
                                "image_url": "https://i.redd.it/cms/215aa380fed69d14_trophy_image_for_mod_101.png",
                                "name": "Mod 101",
                                "url": null
                              }
                            ]
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://www.reddit.com/user/spez/",
                        "username": "spez"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "reddit",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 823,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "t2_1w72",
                          "url": "https://www.reddit.com/user/spez/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RedditProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Karma, cake day, trophies and moderated subreddits",
        "tags": [
          "Reddit"
        ],
        "x-socialtap-endpoint": "reddit.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/reddit/profile_comments": {
      "get": {
        "description": "Returns the public comments a Reddit user wrote, a page at a time, from their username or profile link. Each has its text, permalink, time and score, the post it is on (ID, title and link) and its subreddit, whom it replied to, and whether Reddit marks it as an admin's or moderator's, pinned or removed. Sort by New, Top, Hot or Controversial.\n\nReturns `{data, page, meta}`: `data` holds up to 25 `Comment` items (the shared schema, the same on every platform), newest first with sort=newest (the default), Reddit's Controversial order (most evenly divided votes first), of all time or of the time filter that covers since with sort=controversial, Reddit's Top order (highest score first), of all time or of the time filter that covers since with sort=popular, Reddit's Hot order (recent comments ranked by their votes) with sort=relevance. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Reddit's words: `metrics.like_count` is upvotes (score).\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/reddit/profile_comments/ (Markdown: https://socialtap.dev/docs/reference/reddit/profile_comments/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/reddit/profile_comments/index.md)",
          "url": "https://socialtap.dev/docs/reference/reddit/profile_comments/"
        },
        "operationId": "reddit.profile_comments.list",
        "parameters": [
          {
            "description": "Reddit username, with or without u/ (spez, u/spez, /u/spez), or a profile link on any reddit.com host (www, old, new, np, m: reddit.com/user/spez, reddit.com/u/spez, with a tab such as /comments), or the user's profile subreddit (reddit.com/r/u_spez). Usernames are case-insensitive. A t2_ account ID is refused: Reddit's public pages look users up by name only.",
            "example": "spez",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Reddit username, with or without u/ (spez, u/spez, /u/spez), or a profile link on any reddit.com host (www, old, new, np, m: reddit.com/user/spez, reddit.com/u/spez, with a tab such as /comments), or the user's profile subreddit (reddit.com/r/u_spez). Usernames are case-insensitive. A t2_ account ID is refused: Reddit's public pages look users up by name only.",
              "examples": [
                "spez"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. newest (default): New, newest first. popular: Top, highest score first (of all time, or of the narrowest of Reddit's past hour, day, week, month or year that covers since). relevance: Hot, Reddit's ranking of recent comments by their votes. controversial: Controversial, the most evenly divided votes first (in the same time filter as popular).",
            "example": "newest",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "newest",
              "description": "Order of the results. newest (default): New, newest first. popular: Top, highest score first (of all time, or of the narrowest of Reddit's past hour, day, week, month or year that covers since). relevance: Hot, Reddit's ranking of recent comments by their votes. controversial: Controversial, the most evenly divided votes first (in the same time filter as popular).",
              "enum": [
                "newest",
                "popular",
                "relevance",
                "controversial"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at. On newest the walk stops at the first older comment; on popular and controversial Reddit's own time filter that covers since is applied, so fewer pages are fetched, and every page is filtered exactly.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at. On newest the walk stops at the first older comment; on popular and controversial Reddit's own time filter that covers since is applied, so fewer pages are fetched, and every page is filtered exactly.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 25,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 25,
              "maximum": 25,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://styles.redditmedia.com/t5_3k30p/styles/profileIcon_uj015iwx9s7g1.png",
                            "display_name": null,
                            "id": "t2_1w72",
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/spez/",
                            "username": "spez"
                          },
                          "edited_at": null,
                          "id": "t1_19ruo33ofgh8i",
                          "is_by_post_author": null,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": null,
                            "reply_count": null
                          },
                          "parent_id": null,
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": null,
                              "depth": null,
                              "distinguished": "admin",
                              "is_collapsed": null,
                              "is_deleted": false,
                              "more_replies_count": null,
                              "post": {
                                "comment_count": null,
                                "is_nsfw": null,
                                "is_spoiler": null,
                                "published_at": null,
                                "score": null,
                                "title": "Reddit Announces Q3’26 Earnings (plus AMA!)",
                                "url": "https://www.reddit.com/r/RDDT/comments/1xiupuc/reddit_announces_q326_earnings_plus_ama/"
                              },
                              "reply_to_author": {
                                "avatar_url": null,
                                "display_name": null,
                                "id": null,
                                "is_verified": null,
                                "url": "https://www.reddit.com/user/223331_/",
                                "username": "223331_"
                              },
                              "score": -8,
                              "subreddit": {
                                "id": null,
                                "name": "RDDT",
                                "url": "https://www.reddit.com/r/RDDT/"
                              }
                            }
                          },
                          "post_id": "t3_1xiupuc",
                          "published_at": "2026-10-29T22:42:06Z",
                          "text": "Pretty simple. For people who are already coming to Reddit every week, we have to give them a reason to come back everyday. If you come for sports and entertainment, or food and fashion, or new and trends, or something fun and funny, can you find it simply once you’re here. If th…",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/r/RDDT/comments/1xiupuc/comment/19ruo33ofgh8i/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://styles.redditmedia.com/t5_3k30p/styles/profileIcon_uj015iwx9s7g1.png",
                            "display_name": null,
                            "id": "t2_1w72",
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/spez/",
                            "username": "spez"
                          },
                          "edited_at": null,
                          "id": "t1_19ruo2bw7d6ps",
                          "is_by_post_author": null,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": null,
                            "reply_count": null
                          },
                          "parent_id": null,
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": null,
                              "depth": null,
                              "distinguished": "admin",
                              "is_collapsed": null,
                              "is_deleted": false,
                              "more_replies_count": null,
                              "post": {
                                "comment_count": null,
                                "is_nsfw": null,
                                "is_spoiler": null,
                                "published_at": null,
                                "score": null,
                                "title": "Reddit Announces Q3’26 Earnings (plus AMA!)",
                                "url": "https://www.reddit.com/r/RDDT/comments/1xiupuc/reddit_announces_q326_earnings_plus_ama/"
                              },
                              "reply_to_author": {
                                "avatar_url": null,
                                "display_name": null,
                                "id": null,
                                "is_verified": null,
                                "url": "https://www.reddit.com/user/Forsaken_Detective_2/",
                                "username": "Forsaken_Detective_2"
                              },
                              "score": -10,
                              "subreddit": {
                                "id": null,
                                "name": "RDDT",
                                "url": "https://www.reddit.com/r/RDDT/"
                              }
                            }
                          },
                          "post_id": "t3_1xiupuc",
                          "published_at": "2026-10-29T22:41:37Z",
                          "text": "At a high level, however people want to communicate on the internet, they should be able to do so on Reddit.\n\nWe’ve continually evolved over the years, from just links to text to images (becoming a home for early memes and GIFs) to video and now some audio and beyond.\n\nWe’ve seen…",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/r/RDDT/comments/1xiupuc/comment/19ruo2bw7d6ps/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://styles.redditmedia.com/t5_3k30p/styles/profileIcon_uj015iwx9s7g1.png",
                            "display_name": null,
                            "id": "t2_1w72",
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/spez/",
                            "username": "spez"
                          },
                          "edited_at": null,
                          "id": "t1_19ruo0i3k53he",
                          "is_by_post_author": null,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": 18,
                            "reply_count": null
                          },
                          "parent_id": null,
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": null,
                              "depth": null,
                              "distinguished": "admin",
                              "is_collapsed": null,
                              "is_deleted": false,
                              "more_replies_count": null,
                              "post": {
                                "comment_count": null,
                                "is_nsfw": null,
                                "is_spoiler": null,
                                "published_at": null,
                                "score": null,
                                "title": "About that login screen",
                                "url": "https://www.reddit.com/user/spez/comments/1xiupm0/about_that_login_screen/"
                              },
                              "reply_to_author": {
                                "avatar_url": null,
                                "display_name": null,
                                "id": null,
                                "is_verified": null,
                                "url": "https://www.reddit.com/user/GaryNOVA/",
                                "username": "GaryNOVA"
                              },
                              "score": 18,
                              "subreddit": {
                                "id": null,
                                "name": "u_spez",
                                "url": "https://www.reddit.com/r/u_spez/"
                              }
                            }
                          },
                          "post_id": "t3_1xiupm0",
                          "published_at": "2026-10-29T22:40:29Z",
                          "text": "me too, Gary, me too…",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/user/spez/comments/1xiupm0/comment/19ruo0i3k53he/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "reddit",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 557,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "t2_1w72",
                          "url": "https://www.reddit.com/user/spez/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RedditProfile_commentsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Comment history of a user, sorted New or Top",
        "tags": [
          "Reddit"
        ],
        "x-socialtap-endpoint": "reddit.profile_comments",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "orders": {
            "controversial": "Reddit's Controversial order (most evenly divided votes first), of all time or of the time filter that covers since",
            "newest": "newest first",
            "popular": "Reddit's Top order (highest score first), of all time or of the time filter that covers since",
            "relevance": "Reddit's Hot order (recent comments ranked by their votes)"
          },
          "page_max": 25,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/reddit/search_comments": {
      "get": {
        "description": "Searches public Reddit comments by keyword, across Reddit or in one subreddit, sorted by best match, newest or top. Each has its text, permalink, author and avatar, time, exact score and the comment it replies to, with the post it is on (title, link, score, comment count, NSFW and spoiler marks) and its subreddit.\n\nReturns `{data, page, meta}`: `data` holds up to 10 `Comment` items (the shared schema, the same on every platform), Reddit's search ranking (best match) with sort=relevance (the default), newest first with sort=newest, Reddit's Top: highest score first with sort=popular. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Reddit's words: `metrics.like_count` is upvotes (score).\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/reddit/search_comments/ (Markdown: https://socialtap.dev/docs/reference/reddit/search_comments/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/reddit/search_comments/index.md)",
          "url": "https://socialtap.dev/docs/reference/reddit/search_comments/"
        },
        "operationId": "reddit.search_comments.list",
        "parameters": [
          {
            "description": "Words to find in comment text, matched by Reddit's own search. Reddit's operators pass through: a quoted \"exact phrase\", author:<username>, subreddit:<name>, NOT <word> (upper case; lower-case not is a word).",
            "example": "golang",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find in comment text, matched by Reddit's own search. Reddit's operators pass through: a quoted \"exact phrase\", author:<username>, subreddit:<name>, NOT <word> (upper case; lower-case not is a word).",
              "examples": [
                "golang"
              ],
              "maxLength": 500,
              "type": "string"
            }
          },
          {
            "description": "Only comments in this subreddit: its name (golang), r/golang or its link. Omit to search all of Reddit.",
            "example": "golang",
            "in": "query",
            "name": "subreddit",
            "schema": {
              "description": "Only comments in this subreddit: its name (golang), r/golang or its link. Omit to search all of Reddit.",
              "examples": [
                "golang"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. relevance (default): Reddit's best matches. newest: newest first. popular: the highest-scored comments first (Reddit's Top).",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "relevance",
              "description": "Order of the results. relevance (default): Reddit's best matches. newest: newest first. popular: the highest-scored comments first (Reddit's Top).",
              "enum": [
                "relevance",
                "newest",
                "popular"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at. With sort=newest the walk stops at the first older comment; Reddit's comment search has no date filter of its own, so other sorts filter each page.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at. With sort=newest the walk stops at the first older comment; Reddit's comment search has no date filter of its own, so other sorts filter each page.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 10,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 10,
              "maximum": 10,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://www.redditstatic.com/avatars/defaults/v2/avatar_default_4.png",
                            "display_name": null,
                            "id": null,
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/TheHeretic/",
                            "username": "TheHeretic"
                          },
                          "edited_at": null,
                          "id": "t1_19rgj26rxh943",
                          "is_by_post_author": null,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 391,
                            "reply_count": null
                          },
                          "parent_id": null,
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": null,
                              "depth": null,
                              "distinguished": null,
                              "is_collapsed": null,
                              "is_deleted": null,
                              "more_replies_count": null,
                              "post": {
                                "comment_count": 633,
                                "is_nsfw": false,
                                "is_spoiler": false,
                                "published_at": "2026-10-21T23:38:18Z",
                                "score": 1258,
                                "title": "Aside from hacking TVs to remove ads, what’s another cool/innovative way you’ve used claude to boost your quality of life",
                                "url": "https://www.reddit.com/r/ClaudeAI/comments/1xc31hj/aside_from_hacking_tvs_to_remove_ads_whats/"
                              },
                              "reply_to_author": null,
                              "score": 391,
                              "subreddit": {
                                "id": "t5_7t8hvt",
                                "name": "ClaudeAI",
                                "url": "https://www.reddit.com/r/ClaudeAI/"
                              }
                            }
                          },
                          "post_id": "t3_1xc31hj",
                          "published_at": "2026-10-22T00:29:40Z",
                          "text": "Reverse engineering Microsoft teams to make a golang version that only uses ~120mb of RAM as compared to 3GiB on Mac",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/r/ClaudeAI/comments/1xc31hj/aside_from_hacking_tvs_to_remove_ads_whats/19rgj26rxh943/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://www.redditstatic.com/avatars/defaults/v2/avatar_default_3.png",
                            "display_name": null,
                            "id": null,
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/Conflict-Mother/",
                            "username": "Conflict-Mother"
                          },
                          "edited_at": null,
                          "id": "t1_19s0zx668qjgj",
                          "is_by_post_author": null,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 1,
                            "reply_count": null
                          },
                          "parent_id": "t1_19s0zmg6ic9hh",
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": null,
                              "depth": null,
                              "distinguished": null,
                              "is_collapsed": null,
                              "is_deleted": null,
                              "more_replies_count": null,
                              "post": {
                                "comment_count": 17,
                                "is_nsfw": false,
                                "is_spoiler": false,
                                "published_at": "2026-11-02T11:19:09Z",
                                "score": 0,
                                "title": "Synology has abandaned beloved VideoStation, now I re-create it",
                                "url": "https://www.reddit.com/r/synology/comments/1xlujkl/synology_has_abandaned_beloved_videostation_now_i/"
                              },
                              "reply_to_author": null,
                              "score": 1,
                              "subreddit": {
                                "id": "t5_2s4co",
                                "name": "synology",
                                "url": "https://www.reddit.com/r/synology/"
                              }
                            }
                          },
                          "post_id": "t3_1xlujkl",
                          "published_at": "2026-11-02T11:50:12Z",
                          "text": "yes single binary is the most gain from. In idle status, MyVideoStation in docker occupy about 25MB mem as I see, and even when scanning golang's mem gc is working very well. Because of all htmls are served from embed, it is blazing fast too.",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/r/synology/comments/1xlujkl/synology_has_abandaned_beloved_videostation_now_i/19s0zx668qjgj/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://www.redditstatic.com/shreddit/assets/avatar_over18.png",
                            "display_name": null,
                            "id": null,
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/lispLaiBhari/",
                            "username": "lispLaiBhari"
                          },
                          "edited_at": null,
                          "id": "t1_19s0kg7kv3uzp",
                          "is_by_post_author": null,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 1,
                            "reply_count": null
                          },
                          "parent_id": "t1_19s0jm74i7yxx",
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": null,
                              "depth": null,
                              "distinguished": null,
                              "is_collapsed": null,
                              "is_deleted": null,
                              "more_replies_count": null,
                              "post": {
                                "comment_count": 13,
                                "is_nsfw": false,
                                "is_spoiler": false,
                                "published_at": "2026-11-02T05:33:45Z",
                                "score": 7,
                                "title": "Kuberenetes home lab suggestion",
                                "url": "https://www.reddit.com/r/kubernetes/comments/1xlozgi/kuberenetes_home_lab_suggestion/"
                              },
                              "reply_to_author": null,
                              "score": 1,
                              "subreddit": {
                                "id": "t5_33f68",
                                "name": "kubernetes",
                                "url": "https://www.reddit.com/r/kubernetes/"
                              }
                            }
                          },
                          "post_id": "t3_1xlozgi",
                          "published_at": "2026-11-02T06:03:20Z",
                          "text": "Thanks. So i want to learn Kubernetes along with CI/CD. Currently working in golang application side but wanted to do this setup and experiment.\n\nOne laptop and one mini-PC(mid range), will this suffice to experiment on prem K8S/CI/CD?",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/r/kubernetes/comments/1xlozgi/kuberenetes_home_lab_suggestion/19s0kg7kv3uzp/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "reddit",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 581,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RedditSearch_commentsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Comments by keyword, sitewide or in a subreddit",
        "tags": [
          "Reddit"
        ],
        "x-socialtap-endpoint": "reddit.search_comments",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Reddit's search ranking (best match)",
          "orders": {
            "newest": "newest first",
            "popular": "Reddit's Top: highest score first",
            "relevance": "Reddit's search ranking (best match)"
          },
          "page_max": 10,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/reddit/search_posts": {
      "get": {
        "description": "Searches public Reddit posts by keyword, across Reddit or in one subreddit, sorted by best match, newest, top or most comments. Each has its link, title, time, exact score and comment count, author, subreddit, NSFW and spoiler marks, preview image and every image of a gallery. Set media to get only image, video or gallery posts, and include_body for each post's text. Reddit's operators work as on Reddit: exact phrases, subreddit:, author:, site: and title:.\n\nReturns `{data, page, meta}`: `data` holds up to 7 `Post` items (the shared schema, the same on every platform), Reddit's relevance order (its search ranking) with sort=relevance (the default), Reddit's Comments order (most comments first) with sort=most_comments, newest first with sort=newest, Reddit's Top order (highest score first) with sort=popular. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Reddit's words: `metrics.like_count` is upvotes (score).\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/reddit/search_posts/ (Markdown: https://socialtap.dev/docs/reference/reddit/search_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/reddit/search_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/reddit/search_posts/"
        },
        "operationId": "reddit.search_posts.list",
        "parameters": [
          {
            "description": "Words or a phrase, matched by Reddit's search against post titles and text. Reddit's operators pass through: \"exact phrase\", subreddit:name, author:name, title:word, site:example.com, self:yes, OR, NOT.",
            "example": "golang",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words or a phrase, matched by Reddit's search against post titles and text. Reddit's operators pass through: \"exact phrase\", subreddit:name, author:name, title:word, site:example.com, self:yes, OR, NOT.",
              "examples": [
                "golang generics"
              ],
              "maxLength": 512,
              "type": "string"
            }
          },
          {
            "description": "Only posts in this subreddit: its name (golang), r/golang, or its link (https://www.reddit.com/r/golang/). All of Reddit when omitted.",
            "example": "golang",
            "in": "query",
            "name": "subreddit",
            "schema": {
              "description": "Only posts in this subreddit: its name (golang), r/golang, or its link (https://www.reddit.com/r/golang/). All of Reddit when omitted.",
              "examples": [
                "golang"
              ],
              "maxLength": 256,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. relevance (default): Reddit's best match. newest: newest posts first. popular: Reddit's Top order (highest score first). most_comments: Reddit's Comments order (most comments first).",
            "example": "popular",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "relevance",
              "description": "Order of the results. relevance (default): Reddit's best match. newest: newest posts first. popular: Reddit's Top order (highest score first). most_comments: Reddit's Comments order (most comments first).",
              "enum": [
                "relevance",
                "newest",
                "popular",
                "most_comments"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Reddit's own time filter (past hour, day, week, month or year) is applied when it covers since, so fewer pages are fetched; every page is then filtered by published_at, which is exact. On newest the walk stops at the first older post.",
            "example": "2026-01-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Reddit's own time filter (past hour, day, week, month or year) is applied when it covers since, so fewer pages are fetched; every page is then filtered by published_at, which is exact. On newest the walk stops at the first older post.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only posts that carry media uploaded to Reddit: image (one image or GIF), video (a Reddit video), carousel (a gallery, several images in one post) or any (all three). Reddit's search applies the filter itself, so pages stay full and it works with subreddit, sort, since and until. query can't use site:, url: or self:yes with it. All posts when omitted.",
            "example": "",
            "in": "query",
            "name": "media",
            "schema": {
              "description": "Only posts that carry media uploaded to Reddit: image (one image or GIF), video (a Reddit video), carousel (a gallery, several images in one post) or any (all three). Reddit's search applies the filter itself, so pages stay full and it works with subreddit, sort, since and until. query can't use site:, url: or self:yes with it. All posts when omitted.",
              "enum": [
                "image",
                "video",
                "carousel",
                "any"
              ],
              "type": "string"
            }
          },
          {
            "description": "Also return each post's body (text, mentions) and its exact type, read from Reddit's feed of the page's posts: a second upstream request per page, at the same price. Works with every sort.",
            "example": "",
            "in": "query",
            "name": "include_body",
            "schema": {
              "description": "Also return each post's body (text, mentions) and its exact type, read from Reddit's feed of the page's posts: a second upstream request per page, at the same price. Works with every sort.",
              "type": "boolean"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 7,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 7,
              "maximum": 7,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "type"
                          ],
                          "author": {
                            "avatar_url": null,
                            "display_name": null,
                            "id": "t2_xdr3c",
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/PremiumMeats/",
                            "username": "PremiumMeats"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "t3_1qspau9",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 100,
                            "like_count": 8656,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": null,
                              "crosspost_of": null,
                              "domain": null,
                              "flair": null,
                              "is_archived": null,
                              "is_locked": null,
                              "is_spoiler": false,
                              "link_url": null,
                              "score": 8656,
                              "subreddit": {
                                "id": "t5_2sg5b",
                                "name": "Terraria",
                                "url": "https://www.reddit.com/r/Terraria/"
                              },
                              "upvote_ratio": null
                            }
                          },
                          "platform_type": null,
                          "published_at": "2026-02-01T05:07:18Z",
                          "text": null,
                          "thumbnail_url": "https://a.thumbs.redditmedia.com/9uF17zO2j_PCGq9IlJvjb2cmICxdG7y-6W2oc7z_ei0.jpg",
                          "title": "welcome back, 100% pickaxe power reaver shark",
                          "type": "link",
                          "unknown_fields": [
                            "mentions",
                            "media"
                          ],
                          "url": "https://www.reddit.com/r/Terraria/comments/1qspau9/welcome_back_100_pickaxe_power_reaver_shark/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": null,
                            "display_name": null,
                            "id": "t2_242ljnbakp",
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/rpakyas/",
                            "username": "rpakyas"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "t3_1ubtk8w",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://preview.redd.it/xedwoinqpn8h1.jpeg?width=140&height=140&crop=1%3A1%2Csmart&auto=webp&s=b85a467bdce6a4eb57e7c24bca3db7d7b4c17e2d",
                              "type": "image",
                              "url": "https://i.redd.it/xedwoinqpn8h1.jpeg",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 345,
                            "like_count": 2559,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": null,
                              "crosspost_of": null,
                              "domain": null,
                              "flair": null,
                              "is_archived": null,
                              "is_locked": null,
                              "is_spoiler": false,
                              "link_url": null,
                              "score": 2559,
                              "subreddit": {
                                "id": "t5_40th7s",
                                "name": "buhaydigital",
                                "url": "https://www.reddit.com/r/buhaydigital/"
                              },
                              "upvote_ratio": null
                            }
                          },
                          "platform_type": null,
                          "published_at": "2026-06-21T15:55:36Z",
                          "text": null,
                          "thumbnail_url": "https://preview.redd.it/xedwoinqpn8h1.jpeg?width=140&height=140&crop=1%3A1%2Csmart&auto=webp&s=b85a467bdce6a4eb57e7c24bca3db7d7b4c17e2d",
                          "title": "from $4/hr to $10k/month after 13 years of WFH, my journey",
                          "type": "image",
                          "unknown_fields": [
                            "mentions"
                          ],
                          "url": "https://www.reddit.com/r/buhaydigital/comments/1ubtk8w/from_4hr_to_10kmonth_after_13_years_of_wfh_my/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": null,
                            "display_name": null,
                            "id": "t2_w6crhcklm",
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/ZookeepergameMost817/",
                            "username": "ZookeepergameMost817"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "t3_1wgu40p",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://preview.redd.it/tp97rbcz5nph1.jpeg?width=140&height=140&crop=1%3A1%2Csmart&auto=webp&s=1a0b1993df7ce5a9bab03dbd1ae823904ee5a406",
                              "type": "image",
                              "url": "https://i.redd.it/tp97rbcz5nph1.jpeg",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 101,
                            "like_count": 2372,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": null,
                              "crosspost_of": null,
                              "domain": null,
                              "flair": null,
                              "is_archived": null,
                              "is_locked": null,
                              "is_spoiler": false,
                              "link_url": null,
                              "score": 2372,
                              "subreddit": {
                                "id": "t5_fvy1km",
                                "name": "SATNA_PROJECT",
                                "url": "https://www.reddit.com/r/SATNA_PROJECT/"
                              },
                              "upvote_ratio": null
                            }
                          },
                          "platform_type": null,
                          "published_at": "2026-09-15T08:06:21Z",
                          "text": null,
                          "thumbnail_url": "https://preview.redd.it/tp97rbcz5nph1.jpeg?width=140&height=140&crop=1%3A1%2Csmart&auto=webp&s=1a0b1993df7ce5a9bab03dbd1ae823904ee5a406",
                          "title": "Anthropic hackathon winner just open-sourced his entire Claude Code setup 🔥",
                          "type": "image",
                          "unknown_fields": [
                            "mentions"
                          ],
                          "url": "https://www.reddit.com/r/SATNA_PROJECT/comments/1wgu40p/anthropic_hackathon_winner_just_opensourced_his/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "reddit",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 603,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RedditSearch_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Posts by keyword, with Reddit's search operators",
        "tags": [
          "Reddit"
        ],
        "x-socialtap-endpoint": "reddit.search_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Reddit's relevance order (its search ranking)",
          "orders": {
            "most_comments": "Reddit's Comments order (most comments first)",
            "newest": "newest first",
            "popular": "Reddit's Top order (highest score first)",
            "relevance": "Reddit's relevance order (its search ranking)"
          },
          "page_max": 7,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/reddit/search_profiles": {
      "get": {
        "description": "Searches Reddit users by name and returns them a page at a time, in Reddit's relevance order. Each has its t2_ ID, username, profile link, avatar, description, verified badge and exact total karma. A name or part of one works, in any language and any case.\n\nReturns `{data, page, meta}`: `data` holds up to 7 `Profile` items (the shared schema, the same on every platform), Reddit's relevance order. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/reddit/search_profiles/ (Markdown: https://socialtap.dev/docs/reference/reddit/search_profiles/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/reddit/search_profiles/index.md)",
          "url": "https://socialtap.dev/docs/reference/reddit/search_profiles/"
        },
        "operationId": "reddit.search_profiles.list",
        "parameters": [
          {
            "description": "A name to find Reddit users by, matched by Reddit's people search against usernames (spez, bill gates, tagesschau); case does not matter. A t2_ account ID is refused: Reddit's people search finds nothing by ID.",
            "example": "spez",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "A name to find Reddit users by, matched by Reddit's people search against usernames (spez, bill gates, tagesschau); case does not matter. A t2_ account ID is refused: Reddit's people search finds nothing by ID.",
              "examples": [
                "spez"
              ],
              "maxLength": 500,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 7,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 7,
              "maximum": 7,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://styles.redditmedia.com/t5_3k30p/styles/profileIcon_uj015iwx9s7g1.png",
                          "banner_url": null,
                          "bio": "Reddit CEO",
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": null,
                          "external_links": [],
                          "id": "t2_1w72",
                          "is_private": false,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "comment_karma": null,
                              "contribution_count": null,
                              "is_admin": null,
                              "is_nsfw": null,
                              "is_premium": null,
                              "karma": 941387,
                              "moderated_subreddits": [],
                              "post_karma": null,
                              "trophies": []
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.reddit.moderated_subreddits",
                            "platform_specific.reddit.trophies"
                          ],
                          "url": "https://www.reddit.com/user/spez/",
                          "username": "spez"
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://i.redd.it/snoovatar/avatars/dd4f5ee8-3016-4ba8-b38b-cc9f09c5ff44.png",
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": null,
                          "external_links": [],
                          "id": "t2_w1jdgw3z4",
                          "is_private": false,
                          "is_verified": false,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "comment_karma": null,
                              "contribution_count": null,
                              "is_admin": null,
                              "is_nsfw": null,
                              "is_premium": null,
                              "karma": -1,
                              "moderated_subreddits": [],
                              "post_karma": null,
                              "trophies": []
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.reddit.moderated_subreddits",
                            "platform_specific.reddit.trophies"
                          ],
                          "url": "https://www.reddit.com/user/Spezigeniesser/",
                          "username": "Spezigeniesser"
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://styles.redditmedia.com/t5_23u24h/styles/profileIcon_7jn5mi6ql2wd1.png",
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": null,
                          "external_links": [],
                          "id": "t2_4gm3yvpn",
                          "is_private": false,
                          "is_verified": false,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "comment_karma": null,
                              "contribution_count": null,
                              "is_admin": null,
                              "is_nsfw": null,
                              "is_premium": null,
                              "karma": 11283,
                              "moderated_subreddits": [],
                              "post_karma": null,
                              "trophies": []
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.reddit.moderated_subreddits",
                            "platform_specific.reddit.trophies"
                          ],
                          "url": "https://www.reddit.com/user/spezialzt/",
                          "username": "spezialzt"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "reddit",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 364,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RedditSearch_profilesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Users by name, with karma and avatar",
        "tags": [
          "Reddit"
        ],
        "x-socialtap-endpoint": "reddit.search_profiles",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Reddit's relevance order",
          "page_max": 7,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/reddit/search_subreddits": {
      "get": {
        "description": "Searches public subreddits by keyword and returns them a page at a time, in Reddit's relevance order. Each has its name, ID, link, description and icon, whether it is marked NSFW or quarantined, and the exact weekly visitors and contributions Reddit shows beside it. Queries in any language work.\n\nReturns `{data, page, meta}`: `data` holds up to 10 `Community` items (Reddit calls it a subreddit) (the shared schema, the same on every platform), Reddit's relevance order. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Reddit's words: `metrics.member_count` is subscribers.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/reddit/search_subreddits/ (Markdown: https://socialtap.dev/docs/reference/reddit/search_subreddits/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/reddit/search_subreddits/index.md)",
          "url": "https://socialtap.dev/docs/reference/reddit/search_subreddits/"
        },
        "operationId": "reddit.search_subreddits.list",
        "parameters": [
          {
            "description": "Words to find subreddits by, matched by Reddit's community search against their names and descriptions (golang, home brewing, fußball).",
            "example": "golang",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find subreddits by, matched by Reddit's community search against their names and descriptions (golang, home brewing, fußball).",
              "examples": [
                "golang"
              ],
              "maxLength": 500,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 10,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 10,
              "maximum": 10,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://styles.redditmedia.com/t5_2rc7j/styles/communityIcon_wy4riduoe9k11.png?width=64&frame=1&auto=webp&s=b35b0d214c4c3462cd4d4e0966f04f005cbe2576",
                          "banner_url": null,
                          "categories": [],
                          "created_at": null,
                          "description": "Ask questions and post articles about the Go programming language and related tools, events etc.",
                          "id": "t5_2rc7j",
                          "is_nsfw": false,
                          "metrics": {
                            "member_count": null
                          },
                          "moderators": [],
                          "name": "golang",
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "is_quarantined": false,
                              "member_nickname": null,
                              "weekly_contribution_count": 680,
                              "weekly_visitor_count": 74052
                            }
                          },
                          "privacy": null,
                          "rules": [],
                          "title": null,
                          "unknown_fields": [
                            "categories",
                            "moderators",
                            "rules"
                          ],
                          "url": "https://www.reddit.com/r/golang/"
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://styles.redditmedia.com/t5_3hpdu/styles/communityIcon_g9aiugyvoo7b1.jpg?width=64&frame=1&auto=webp&s=5419ac02a033662bff6352aa4e1c91d0034e4188",
                          "banner_url": null,
                          "categories": [],
                          "created_at": null,
                          "description": "/r/golang2: an unofficial plan B subreddit in case they decide to screw the official one",
                          "id": "t5_3hpdu",
                          "is_nsfw": false,
                          "metrics": {
                            "member_count": null
                          },
                          "moderators": [],
                          "name": "golang2",
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "is_quarantined": false,
                              "member_nickname": null,
                              "weekly_contribution_count": 0,
                              "weekly_visitor_count": 5
                            }
                          },
                          "privacy": null,
                          "rules": [],
                          "title": null,
                          "unknown_fields": [
                            "categories",
                            "moderators",
                            "rules"
                          ],
                          "url": "https://www.reddit.com/r/golang2/"
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://styles.redditmedia.com/t5_2fwo/styles/communityIcon_1bqa1ibfp8q11.png?width=64&frame=1&auto=webp&s=2545f3c0332e412c8635f5f2a5868c0e857ef040",
                          "banner_url": null,
                          "categories": [],
                          "created_at": null,
                          "description": "Computer Programming",
                          "id": "t5_2fwo",
                          "is_nsfw": false,
                          "metrics": {
                            "member_count": null
                          },
                          "moderators": [],
                          "name": "programming",
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "is_quarantined": false,
                              "member_nickname": null,
                              "weekly_contribution_count": 1735,
                              "weekly_visitor_count": 217174
                            }
                          },
                          "privacy": null,
                          "rules": [],
                          "title": null,
                          "unknown_fields": [
                            "categories",
                            "moderators",
                            "rules"
                          ],
                          "url": "https://www.reddit.com/r/programming/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "reddit",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 660,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RedditSearch_subredditsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Subreddits by keyword, with weekly visitors",
        "tags": [
          "Reddit"
        ],
        "x-socialtap-endpoint": "reddit.search_subreddits",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Reddit's relevance order",
          "page_max": 10,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "community",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/reddit/subreddit": {
      "get": {
        "description": "Returns a public subreddit from its name or link: title, description, rules with their explanations, creation date, privacy, NSFW flag and icon. It also has the banner, what the subreddit calls its members, and the weekly visitors and contributions Reddit shows.\n\nReturns `{data, meta}`: `data` is a `Community` object (Reddit calls it a subreddit) (the shared schema, the same on every platform). Null means unknown.\n\nIn Reddit's words: `metrics.member_count` is subscribers.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/reddit/subreddit/ (Markdown: https://socialtap.dev/docs/reference/reddit/subreddit/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/reddit/subreddit/index.md)",
          "url": "https://socialtap.dev/docs/reference/reddit/subreddit/"
        },
        "operationId": "reddit.subreddit.get",
        "parameters": [
          {
            "description": "The subreddit: its link on any reddit.com host (www, old, new, np, m, sh), any of its tabs included (/about, /new, /top, /wiki), r/<name>, or its bare name (golang). Names are case-insensitive.",
            "example": "https://www.reddit.com/r/golang/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The subreddit: its link on any reddit.com host (www, old, new, np, m, sh), any of its tabs included (/about, /new, /top, /wiki), r/<name>, or its bare name (golang). Names are case-insensitive.",
              "examples": [
                "https://www.reddit.com/r/golang/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://styles.redditmedia.com/t5_2rc7j/styles/communityIcon_wy4riduoe9k11.png?width=128&frame=1&auto=webp&s=a9c9b6dba0f0655d79102b24e34b9d04706eb0d6",
                        "banner_url": "https://styles.redditmedia.com/t5_2rc7j/styles/bannerBackgroundImage_k15p9ugyd9k11.png?frame=1&auto=webp&s=d0fe21082f615ee236e0aff56e7f3c884565c48a",
                        "categories": [],
                        "created_at": "2009-11-11T00:54:28Z",
                        "description": "Ask questions and post articles about the Go programming language and related tools, events etc.",
                        "id": "t5_2rc7j",
                        "is_nsfw": false,
                        "metrics": {
                          "member_count": null
                        },
                        "moderators": [],
                        "name": "golang",
                        "platform": "reddit",
                        "platform_specific": {
                          "reddit": {
                            "is_quarantined": false,
                            "member_nickname": "gophers",
                            "weekly_contribution_count": 680,
                            "weekly_visitor_count": 74052
                          }
                        },
                        "privacy": "public",
                        "rules": [
                          {
                            "description": "Post is not in keeping with an inclusive and friendly technical atmosphere.",
                            "title": "Be friendly and welcoming."
                          },
                          {
                            "description": "Remember that people have varying communication styles and that not everyone is using their native language. (Meaning and tone can be lost in translation.)",
                            "title": "Be patient."
                          },
                          {
                            "description": "Productive communication requires effort. Think about how your words will be interpreted. Remember that sometimes it is best to refrain entirely from commenting.\n\nCheck for your answer in the subreddit FAQs and the Tour of Go before posting common questions, please.",
                            "title": "Be thoughtful."
                          }
                        ],
                        "title": "The Go Programming Language",
                        "unknown_fields": [
                          "categories",
                          "moderators"
                        ],
                        "url": "https://www.reddit.com/r/golang/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "reddit",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 513,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "community",
                          "id": "t5_2rc7j",
                          "url": "https://www.reddit.com/r/golang/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RedditSubredditResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Rules, description and weekly visitors",
        "tags": [
          "Reddit"
        ],
        "x-socialtap-endpoint": "reddit.subreddit",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "community",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/reddit/subreddit_posts": {
      "get": {
        "description": "Returns a public subreddit's posts a page at a time, sorted Best, Hot, New, Top, Rising or Controversial. Top and Controversial take a time range, from the past hour to all time. Each post has its title and full text, author, exact score and upvote ratio, comment and award counts, images, gallery or video, flair, and whether it is pinned, NSFW, a spoiler, locked, archived or a crosspost. Send the subreddit's link, r/<name> or its name; r/popular works too.\n\nReturns `{data, page, meta}`: `data` holds up to 25 `Post` items (the shared schema, the same on every platform), Reddit's Best order (its default ranking of a subreddit's posts) with sort=best (the default), Reddit's Controversial order (most evenly divided votes first, within the time filter since picks) with sort=controversial, Reddit's Hot order (recent posts gaining votes fast first) with sort=hot, newest first with sort=newest, Reddit's Top order (highest score first, within the time filter since picks) with sort=popular, Reddit's Rising order (new posts gaining votes fastest first) with sort=rising. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Reddit's words: `metrics.like_count` is upvotes (score).\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/reddit/subreddit_posts/ (Markdown: https://socialtap.dev/docs/reference/reddit/subreddit_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/reddit/subreddit_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/reddit/subreddit_posts/"
        },
        "operationId": "reddit.subreddit_posts.list",
        "parameters": [
          {
            "description": "The subreddit: its link on any reddit.com host (www, old, new, np, m, sh), any of its tabs included (/new, /top/?t=week, /about), r/<name>, or its bare name (golang). Names are case-insensitive. r/popular, Reddit's feed of popular posts, works too.",
            "example": "https://www.reddit.com/r/golang/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The subreddit: its link on any reddit.com host (www, old, new, np, m, sh), any of its tabs included (/new, /top/?t=week, /about), r/<name>, or its bare name (golang). Names are case-insensitive. r/popular, Reddit's feed of popular posts, works too.",
              "examples": [
                "https://www.reddit.com/r/golang/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. Reddit's orders: best (default, Reddit's own ranking), hot, newest, popular (Reddit's Top: highest score first), rising or controversial. A link's tab does not set it.",
            "example": "best",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "best",
              "description": "Order of the results. Reddit's orders: best (default, Reddit's own ranking), hot, newest, popular (Reddit's Top: highest score first), rising or controversial. A link's tab does not set it.",
              "enum": [
                "best",
                "hot",
                "newest",
                "popular",
                "rising",
                "controversial"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only posts at or after this time: RFC 3339 or a date (midnight UTC). On popular and controversial it also picks Reddit's time filter (past hour, day, week, month or year; all time without since), the narrowest that covers it, so the ranking counts that span; every page is then filtered exactly by published_at. On newest paging stops at the first older post.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only posts at or after this time: RFC 3339 or a date (midnight UTC). On popular and controversial it also picks Reddit's time filter (past hour, day, week, month or year; all time without since), the narrowest that covers it, so the ranking counts that span; every page is then filtered exactly by published_at. On newest paging stops at the first older post.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 25,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 25,
              "maximum": 25,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://styles.redditmedia.com/t5_a1v2lk/styles/profileIcon_snoo-nftv2_bmZ0X2VpcDE1NToxMzdfZWI5NTlhNzE1ZGZmZmU2ZjgyZjQ2MDU1MzM5ODJjNDg1OWNiMTRmZV8yMzcwNDc5Mw_rare_bab5aafc-9be8-4a21-9291-292d69269d8f-headshot.png?width=64&height=64&frame=1&auto=webp&crop=64%3A64%2Csmart&s=91b4656…",
                            "display_name": null,
                            "id": "t2_oamvoow25",
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/masteryourown/",
                            "username": "masteryourown"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "t3_1xlsvt6",
                          "is_nsfw": false,
                          "is_pinned": false,
                          "is_sponsored": false,
                          "language": "en",
                          "media": [],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 18,
                            "like_count": 50,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": 0,
                              "crosspost_of": null,
                              "domain": "self.golang",
                              "flair": null,
                              "is_archived": false,
                              "is_locked": false,
                              "is_spoiler": false,
                              "link_url": null,
                              "score": 50,
                              "subreddit": {
                                "id": "t5_2rc7j",
                                "name": "golang",
                                "url": "https://www.reddit.com/r/golang/"
                              },
                              "upvote_ratio": 0.9310344827586207
                            }
                          },
                          "platform_type": "text",
                          "published_at": "2026-11-02T09:39:53Z",
                          "text": "I am a Go beginner, I had understood the concepts of go and now I want to implement the things using Go, I want to built projects but not typically looking for beginner ones like web scraper or task/expense tracker, I want something intermediate level or hard that actually challe…",
                          "thumbnail_url": null,
                          "title": "Looking for interesting Go projects beyond the usual beginner stuff",
                          "type": "text",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/r/golang/comments/1xlsvt6/looking_for_interesting_go_projects_beyond_the/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://www.redditstatic.com/avatars/defaults/v2/avatar_default_3.png",
                            "display_name": null,
                            "id": "t2_opw76rkuj",
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/theadamwey/",
                            "username": "theadamwey"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "t3_1x7oe1w",
                          "is_nsfw": false,
                          "is_pinned": false,
                          "is_sponsored": false,
                          "language": "en",
                          "media": [],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 46,
                            "like_count": 551,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": 0,
                              "crosspost_of": null,
                              "domain": "github.com",
                              "flair": "discussion",
                              "is_archived": false,
                              "is_locked": false,
                              "is_spoiler": false,
                              "link_url": "https://github.com/valimised/ivxv",
                              "score": 551,
                              "subreddit": {
                                "id": "t5_2rc7j",
                                "name": "golang",
                                "url": "https://www.reddit.com/r/golang/"
                              },
                              "upvote_ratio": 0.9910873440285205
                            }
                          },
                          "platform_type": "link",
                          "published_at": "2026-10-16T18:42:44Z",
                          "text": null,
                          "thumbnail_url": null,
                          "title": "Estonia's election system is mostly programmed in Go. I came across the open source github repo and wanted to share.",
                          "type": "link",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/r/golang/comments/1x7oe1w/estonias_election_system_is_mostly_programmed_in/"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://styles.redditmedia.com/t5_axsmo/styles/profileIcon_x1liwt4w1uba1.jpg?width=64&height=64&frame=1&auto=webp&crop=64%3A64%2Csmart&s=29a9dd5c24114953ada9bdfbc26a3c0049e0f6b7",
                            "display_name": null,
                            "id": "t2_iaoxg",
                            "is_verified": null,
                            "url": "https://www.reddit.com/user/luxurioust/",
                            "username": "luxurioust"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "t3_1xlr4rr",
                          "is_nsfw": false,
                          "is_pinned": false,
                          "is_sponsored": false,
                          "language": "und",
                          "media": [],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 1,
                            "like_count": 15,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "reddit",
                          "platform_specific": {
                            "reddit": {
                              "award_count": 0,
                              "crosspost_of": null,
                              "domain": "self.golang",
                              "flair": null,
                              "is_archived": false,
                              "is_locked": false,
                              "is_spoiler": false,
                              "link_url": null,
                              "score": 15,
                              "subreddit": {
                                "id": "t5_2rc7j",
                                "name": "golang",
                                "url": "https://www.reddit.com/r/golang/"
                              },
                              "upvote_ratio": 0.9411764705882353
                            }
                          },
                          "platform_type": "multi_media",
                          "published_at": "2026-11-02T07:45:24Z",
                          "text": "Excelize is a library written in pure Go providing a set of functions that allow you to write to and read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and writing spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports complex components by h…",
                          "thumbnail_url": null,
                          "title": "Excelize 2.11.1 Released - Open-source library for spreadsheet",
                          "type": "text",
                          "unknown_fields": [],
                          "url": "https://www.reddit.com/r/golang/comments/1xlr4rr/excelize_2111_released_opensource_library_for/"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "reddit",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 983,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "community",
                          "id": "t5_2rc7j",
                          "url": "https://www.reddit.com/r/golang/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RedditSubreddit_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Hot, New, Top or Rising, with exact scores",
        "tags": [
          "Reddit"
        ],
        "x-socialtap-endpoint": "reddit.subreddit_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Reddit's Best order (its default ranking of a subreddit's posts)",
          "orders": {
            "best": "Reddit's Best order (its default ranking of a subreddit's posts)",
            "controversial": "Reddit's Controversial order (most evenly divided votes first, within the time filter since picks)",
            "hot": "Reddit's Hot order (recent posts gaining votes fast first)",
            "newest": "newest first",
            "popular": "Reddit's Top order (highest score first, within the time filter since picks)",
            "rising": "Reddit's Rising order (new posts gaining votes fastest first)"
          },
          "page_max": 25,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/reddit/transcript": {
      "get": {
        "description": "Returns the timed transcript of a public Reddit video post from its link or ID, from Reddit's captions or, when it has none, its audio. Each segment has its start and end time, and text holds the whole transcript. Crossposts of a video, videos inside a text post, and v.redd.it, redd.it and app share links work too.\n\nReturns `{data, meta}`: `data` is a `Transcript` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit (captions) or 2 credits + 2 per started minute of media (speech-to-text) per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/reddit/transcript/ (Markdown: https://socialtap.dev/docs/reference/reddit/transcript/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/reddit/transcript/index.md)",
          "url": "https://socialtap.dev/docs/reference/reddit/transcript/"
        },
        "operationId": "reddit.transcript.get",
        "parameters": [
          {
            "description": "Reddit video post URL: a post's page on any reddit.com host (www, old, new, np, m, sh), with or without its subreddit or slug, a comment's permalink (its post is transcribed), a redd.it short link, an app share link (/r/<subreddit>/s/<code>), a v.redd.it video link or a link to one of its files, or the post's ID (t3_ prefix optional). A crosspost of a video and a text post with a video in its body are transcribed too.",
            "example": "https://www.reddit.com/r/HumansBeingBros/comments/1xkav20/guy_saving_the_deer/",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Reddit video post URL: a post's page on any reddit.com host (www, old, new, np, m, sh), with or without its subreddit or slug, a comment's permalink (its post is transcribed), a redd.it short link, an app share link (/r/<subreddit>/s/<code>), a v.redd.it video link or a link to one of its files, or the post's ID (t3_ prefix optional). A crosspost of a video and a text post with a video in its body are transcribed too.",
              "examples": [
                "https://www.reddit.com/r/HumansBeingBros/comments/1xkav20/guy_saving_the_deer/"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The spoken language. Without lang or with English (en, en-GB…), Reddit's own captions, which are English only, whatever is spoken. Any other language is transcribed by speech-to-text in it instead (meta.source = asr, priced per minute). For a video Reddit has no captions for, speech-to-text runs either way, detecting the language without lang.",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The spoken language. Without lang or with English (en, en-GB…), Reddit's own captions, which are English only, whatever is spoken. Any other language is transcribed by speech-to-text in it instead (meta.source = asr, priced per minute). For a video Reddit has no captions for, speech-to-text runs either way, detecting the language without lang.",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "available_languages": [
                          "en"
                        ],
                        "duration_ms": 94000,
                        "id": "t3_1xkav20",
                        "is_auto_generated": true,
                        "language": "en",
                        "platform": "reddit",
                        "platform_specific": {
                          "reddit": {
                            "caption_url": "https://v.redd.it/4xartwq86tyh1/wh_ben_en.vtt",
                            "video_id": "4xartwq86tyh1"
                          }
                        },
                        "segments": [
                          {
                            "end_ms": 15020,
                            "start_ms": 0,
                            "text": "He's going to be safe after some life. Oh, it's a little bit old. It's a little"
                          },
                          {
                            "end_ms": 29980,
                            "start_ms": 15020,
                            "text": "bit old. It's a little"
                          },
                          {
                            "end_ms": 29980,
                            "start_ms": 29980,
                            "text": "bit old."
                          }
                        ],
                        "source": "captions",
                        "text": "He's going to be safe after some life. Oh, it's a little bit old. It's a little bit old. It's a little bit old. A little bit old. It's a little bit old. There's a question. Good, good, bye, bye. Good bye, bye, bye.",
                        "url": "https://www.reddit.com/r/HumansBeingBros/comments/1xkav20/guy_saving_the_deer/"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "reddit",
                        "source": "captions",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 2591,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "t3_1xkav20",
                          "url": "https://www.reddit.com/r/HumansBeingBros/comments/1xkav20/guy_saving_the_deer/"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RedditTranscriptResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "no_transcript": {
                    "$ref": "#/components/examples/no_transcript"
                  },
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.\n\n`no_transcript`: The video or audio exists but has no transcript: no caption track and no speech to transcribe. Do not retry. If the platform offers other languages, try one with lang.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Video post transcript, from captions or audio",
        "tags": [
          "Reddit"
        ],
        "x-socialtap-endpoint": "reddit.transcript",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 122,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "captions"
            },
            {
              "credits": 2,
              "label": "2 credits + 2 per started minute of media",
              "max": 122,
              "per": 2,
              "source": "asr",
              "unit": "media_minute",
              "unit_max": 60
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "transcript",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/requests": {
      "get": {
        "description": "Every endpoint request the account made, newest first, cursor-paged: its endpoint, params, status, outcome, credits, latency and whether the cache answered, filtered by endpoint, key, outcome, surface and time, and searched by the params' values (q: a handle, a link or an ID). Requests are kept for `log_retention_s` (30 days), at most `log_max_rows` (1000000) per account. Responses are kept only with keep_response_bodies on (GET /v1/requests/{id}/response). A request appears within about 10 seconds. Requests refused before any work are not listed (the runaway-protection ceiling's: GET /v1/usage/rate counts them; over the failure budget or while the API was paused: GET /v1/usage does). Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "requests.list",
        "parameters": [
          {
            "description": "Only this endpoint ID (youtube.transcript).",
            "in": "query",
            "name": "endpoint",
            "schema": {
              "maxLength": 100,
              "type": "string"
            }
          },
          {
            "description": "Only this key's requests.",
            "in": "query",
            "name": "api_key_id",
            "schema": {
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "description": "ok (answered with data), error (any failure), or one error code (not_found).",
            "in": "query",
            "name": "outcome",
            "schema": {
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "description": "Only requests that reached the API this way: rest (an HTTP request), mcp (an MCP tool call) or job (a request of a job).",
            "in": "query",
            "name": "surface",
            "schema": {
              "enum": [
                "rest",
                "mcp",
                "job"
              ],
              "type": "string"
            }
          },
          {
            "description": "Made at or after: RFC 3339 or a date (UTC).",
            "in": "query",
            "name": "since",
            "schema": {
              "maxLength": 40,
              "type": "string"
            }
          },
          {
            "description": "Made before: RFC 3339 or a date (UTC).",
            "in": "query",
            "name": "until",
            "schema": {
              "maxLength": 40,
              "type": "string"
            }
          },
          {
            "description": "Only requests whose params contain every word of q (words split on spaces, each at least 3 characters): anywhere in a param's value, ignoring case, so a handle, part of a link or a video ID finds the requests that sent it. Param names are not searched; control characters are refused.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 200,
              "minLength": 3,
              "type": "string"
            }
          },
          {
            "description": "Requests per page (default 25, at most 100).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page; omit to start from the newest.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "api_key_id": {
                            "description": "The key that made it (key_…).",
                            "type": "string"
                          },
                          "cached": {
                            "description": "true when served from the cache.",
                            "type": "boolean"
                          },
                          "client_request_id": {
                            "description": "The client-request-id header it was sent with; null when none.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "created_at": {
                            "description": "When it was made, RFC 3339 UTC (milliseconds).",
                            "format": "date-time",
                            "type": "string"
                          },
                          "credits_charged": {
                            "description": "Credits charged (0: failures and cache hits are free).",
                            "type": "integer"
                          },
                          "endpoint": {
                            "description": "Endpoint ID (youtube.transcript).",
                            "type": "string"
                          },
                          "http_status": {
                            "description": "The answer's HTTP status.",
                            "type": "integer"
                          },
                          "id": {
                            "description": "The request ID: meta.request_id of its answer and its request-id header.",
                            "type": "string"
                          },
                          "latency_ms": {
                            "description": "Time from receiving the request to answering it, in milliseconds.",
                            "type": "integer"
                          },
                          "object": {
                            "description": "Always request.",
                            "enum": [
                              "request"
                            ],
                            "type": "string"
                          },
                          "outcome": {
                            "description": "ok, or the error code it answered.",
                            "type": "string"
                          },
                          "params": {
                            "additionalProperties": {
                              "type": "string"
                            },
                            "description": "The query params as sent (at most 32; a value longer than 2048 characters is cut). Run the request again with them.",
                            "type": "object"
                          },
                          "params_truncated": {
                            "description": "true when a param or a value was cut: params is not the whole request.",
                            "type": "boolean"
                          },
                          "response_body": {
                            "description": "Whether its answer's body was kept (GET /v1/requests/{id}/response returns it).",
                            "properties": {
                              "expires_at": {
                                "description": "When the kept body is (or was) deleted, RFC 3339 UTC; null when off or not_stored.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "size_bytes": {
                                "description": "The whole answer body's size in bytes; null when off or not_stored.",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "status": {
                                "description": "stored: GET /v1/requests/{id}/response returns it until expires_at. expired: it was kept, and deleted 7 days after the request. off: the account was not keeping response bodies when the request was made (keep_response_bodies). not_stored: it was on, but this body could not be stored, or it answered without a charge past the small allowance of those kept per minute (charged answers are always kept).",
                                "enum": [
                                  "stored",
                                  "expired",
                                  "off",
                                  "not_stored"
                                ],
                                "type": "string"
                              },
                              "truncated": {
                                "description": "true when the answer was longer than 1 MB: only its first 1 MB were kept.",
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "status",
                              "size_bytes",
                              "truncated",
                              "expires_at"
                            ],
                            "type": "object"
                          },
                          "surface": {
                            "description": "How it reached the API: rest (an HTTP request), mcp (an MCP tool call) or job (a request of a job). New values may be added.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "object",
                          "id",
                          "created_at",
                          "endpoint",
                          "api_key_id",
                          "params",
                          "params_truncated",
                          "http_status",
                          "outcome",
                          "credits_charged",
                          "latency_ms",
                          "cached",
                          "surface",
                          "client_request_id",
                          "response_body"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List requests, newest first (the request log)",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "List requests, newest first (the request log)",
        "tags": [
          "Requests"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/requests/{id}": {
      "get": {
        "description": "One request of the request log by its ID (meta.request_id of its answer). Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "requests.get",
        "parameters": [
          {
            "description": "Request ID (meta.request_id, the request-id header).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "api_key_id": {
                          "description": "The key that made it (key_…).",
                          "type": "string"
                        },
                        "cached": {
                          "description": "true when served from the cache.",
                          "type": "boolean"
                        },
                        "client_request_id": {
                          "description": "The client-request-id header it was sent with; null when none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "created_at": {
                          "description": "When it was made, RFC 3339 UTC (milliseconds).",
                          "format": "date-time",
                          "type": "string"
                        },
                        "credits_charged": {
                          "description": "Credits charged (0: failures and cache hits are free).",
                          "type": "integer"
                        },
                        "endpoint": {
                          "description": "Endpoint ID (youtube.transcript).",
                          "type": "string"
                        },
                        "http_status": {
                          "description": "The answer's HTTP status.",
                          "type": "integer"
                        },
                        "id": {
                          "description": "The request ID: meta.request_id of its answer and its request-id header.",
                          "type": "string"
                        },
                        "latency_ms": {
                          "description": "Time from receiving the request to answering it, in milliseconds.",
                          "type": "integer"
                        },
                        "object": {
                          "description": "Always request.",
                          "enum": [
                            "request"
                          ],
                          "type": "string"
                        },
                        "outcome": {
                          "description": "ok, or the error code it answered.",
                          "type": "string"
                        },
                        "params": {
                          "additionalProperties": {
                            "type": "string"
                          },
                          "description": "The query params as sent (at most 32; a value longer than 2048 characters is cut). Run the request again with them.",
                          "type": "object"
                        },
                        "params_truncated": {
                          "description": "true when a param or a value was cut: params is not the whole request.",
                          "type": "boolean"
                        },
                        "response_body": {
                          "description": "Whether its answer's body was kept (GET /v1/requests/{id}/response returns it).",
                          "properties": {
                            "expires_at": {
                              "description": "When the kept body is (or was) deleted, RFC 3339 UTC; null when off or not_stored.",
                              "format": "date-time",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "size_bytes": {
                              "description": "The whole answer body's size in bytes; null when off or not_stored.",
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "status": {
                              "description": "stored: GET /v1/requests/{id}/response returns it until expires_at. expired: it was kept, and deleted 7 days after the request. off: the account was not keeping response bodies when the request was made (keep_response_bodies). not_stored: it was on, but this body could not be stored, or it answered without a charge past the small allowance of those kept per minute (charged answers are always kept).",
                              "enum": [
                                "stored",
                                "expired",
                                "off",
                                "not_stored"
                              ],
                              "type": "string"
                            },
                            "truncated": {
                              "description": "true when the answer was longer than 1 MB: only its first 1 MB were kept.",
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "status",
                            "size_bytes",
                            "truncated",
                            "expires_at"
                          ],
                          "type": "object"
                        },
                        "surface": {
                          "description": "How it reached the API: rest (an HTTP request), mcp (an MCP tool call) or job (a request of a job). New values may be added.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "created_at",
                        "endpoint",
                        "api_key_id",
                        "params",
                        "params_truncated",
                        "http_status",
                        "outcome",
                        "credits_charged",
                        "latency_ms",
                        "cached",
                        "surface",
                        "client_request_id",
                        "response_body"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get a request from the request log",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Get a request from the request log",
        "tags": [
          "Requests"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/requests/{id}/response": {
      "get": {
        "description": "The body and status a request returned, without running it again: kept only while keep_response_bodies is on, for `response_body_retention_s` (7 days), at most `response_body_max_bytes` (1 MB) each; otherwise not_found (details.reason). Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "requests.get_response",
        "parameters": [
          {
            "description": "Request ID (meta.request_id, the request-id header).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "body": {
                          "description": "The answer's body exactly as it was sent: JSON text ({data, meta} or {error}), parse it to use it. When truncated, its first 1 MB (cut at a character boundary): not valid JSON.",
                          "type": "string"
                        },
                        "expires_at": {
                          "description": "When the kept body is deleted, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "http_status": {
                          "description": "The answer's HTTP status.",
                          "type": "integer"
                        },
                        "object": {
                          "description": "Always request_response.",
                          "enum": [
                            "request_response"
                          ],
                          "type": "string"
                        },
                        "request_id": {
                          "description": "The request it answered.",
                          "type": "string"
                        },
                        "size_bytes": {
                          "description": "The whole answer body's size in bytes (body is shorter when truncated).",
                          "type": "integer"
                        },
                        "truncated": {
                          "description": "true when the answer was longer than 1 MB and body holds only its start.",
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "object",
                        "request_id",
                        "http_status",
                        "body",
                        "size_bytes",
                        "truncated",
                        "expires_at"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get the response a request returned",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Get the response a request returned",
        "tags": [
          "Requests"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/rumble/comments": {
      "get": {
        "description": "Returns the public comments on a Rumble video, short or live stream, replies included, a page at a time, newest first or by likes. Each has its text, posting time, likes and dislikes, reply count, the comment a reply answers, a permalink, and the commenter's username, name, avatar and badges, with whether the video's own channel wrote it. Accepts any Rumble video link, embed links included, or a video ID.\n\nReturns `{data, page, meta}`: `data` holds up to 500 `Comment` items (the shared schema, the same on every platform), newest first with sort=newest (the default), Rumble's Sort by likes order of comments, each followed by its replies with sort=popular. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/rumble/comments/ (Markdown: https://socialtap.dev/docs/reference/rumble/comments/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/rumble/comments/index.md)",
          "url": "https://socialtap.dev/docs/reference/rumble/comments/"
        },
        "operationId": "rumble.comments.list",
        "parameters": [
          {
            "description": "Rumble video, short or live stream URL (rumble.com/v…-title.html, /shorts/v…, /share/v…, /embed/v…/) or a video ID (v…).",
            "example": "https://rumble.com/shorts/v7h29za",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Rumble video, short or live stream URL (rumble.com/v…-title.html, /shorts/v…, /share/v…, /embed/v…/) or a video ID (v…).",
              "examples": [
                "https://rumble.com/v79xhhm-discovery-why-glenn-wants-israel-to-sue-the-new-york-times.html"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. newest (default): every comment and reply, newest first. popular: Rumble's Sort by likes order of comments, each followed by its replies.",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "newest",
              "description": "Order of the results. newest (default): every comment and reply, newest first. popular: Rumble's Sort by likes order of comments, each followed by its replies.",
              "enum": [
                "newest",
                "popular"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at, which Rumble shows to the minute. Replies count as items: on newest the walk stops at the first comment or reply older than since.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at, which Rumble shows to the minute. Replies count as items: on newest the walk stops at the first comment or reply older than since.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 500,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 500,
              "maximum": 500,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": "https://hugh.cdn.rumble.cloud/video/z0/e/b/M/g/ebMgr.asF.1-4qu5ac-tnkdxy.jpeg",
                            "display_name": "inshallakhan",
                            "id": null,
                            "is_verified": false,
                            "url": "https://rumble.com/user/inshallakhan",
                            "username": "user/inshallakhan"
                          },
                          "edited_at": null,
                          "id": "620403472",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 0,
                            "reply_count": 0
                          },
                          "parent_id": null,
                          "platform": "rumble",
                          "platform_specific": {
                            "rumble": {
                              "author_badges": [],
                              "dislike_count": 0
                            }
                          },
                          "post_id": "v7h29za",
                          "published_at": "2026-10-23T03:31:00Z",
                          "text": "oh 😯😯",
                          "unknown_fields": [],
                          "url": "https://rumble.com/shorts/v7h29za#comment-620403472"
                        },
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": "https://hugh.cdn.rumble.cloud/video/z0/C/E/l/b/CElbr.asF-4pzq1o-ti0cx0.jpeg",
                            "display_name": "CassandraB89",
                            "id": null,
                            "is_verified": false,
                            "url": "https://rumble.com/user/CassandraB89",
                            "username": "user/CassandraB89"
                          },
                          "edited_at": null,
                          "id": "620356964",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 0,
                            "reply_count": 0
                          },
                          "parent_id": null,
                          "platform": "rumble",
                          "platform_specific": {
                            "rumble": {
                              "author_badges": [],
                              "dislike_count": 0
                            }
                          },
                          "post_id": "v7h29za",
                          "published_at": "2026-10-22T13:01:00Z",
                          "text": "🐈👌🏻🧡",
                          "unknown_fields": [],
                          "url": "https://rumble.com/shorts/v7h29za#comment-620356964"
                        },
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": null,
                            "display_name": "SkyeWalker0504",
                            "id": null,
                            "is_verified": false,
                            "url": "https://rumble.com/user/SkyeWalker0504",
                            "username": "user/SkyeWalker0504"
                          },
                          "edited_at": null,
                          "id": "620301964",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": null,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 1,
                            "reply_count": 0
                          },
                          "parent_id": null,
                          "platform": "rumble",
                          "platform_specific": {
                            "rumble": {
                              "author_badges": [],
                              "dislike_count": 0
                            }
                          },
                          "post_id": "v7h29za",
                          "published_at": "2026-10-21T15:29:00Z",
                          "text": "Looks like a Minecraft cat.",
                          "unknown_fields": [],
                          "url": "https://rumble.com/shorts/v7h29za#comment-620301964"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "rumble",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 359,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "v7h29za",
                          "url": "https://rumble.com/v7h29za"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "end"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RumbleCommentsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Comments and replies on a video or live stream",
        "tags": [
          "Rumble"
        ],
        "x-socialtap-endpoint": "rumble.comments",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "orders": {
            "newest": "newest first",
            "popular": "Rumble's Sort by likes order of comments, each followed by its replies"
          },
          "page_max": 500,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/rumble/engagement": {
      "get": {
        "description": "Returns a Rumble channel's or user's engagement rate per follower and per view, computed over its latest videos, shorts or live streams. The same request returns the profile, each video with its exact counts and its own rate compared with the account's typical video, views, likes, comments and reposts per video, median views, comment-to-like ratio, posting cadence, and the top and bottom video. Accepts a channel or user name, any channel or user link, or a channel ID.\n\nReturns `{data, meta}`: `data` is a `Engagement` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/rumble/engagement/ (Markdown: https://socialtap.dev/docs/reference/rumble/engagement/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/rumble/engagement/index.md)",
          "url": "https://socialtap.dev/docs/reference/rumble/engagement/"
        },
        "operationId": "rumble.engagement.get",
        "parameters": [
          {
            "description": "Rumble channel or user: a bare name (Bongino: a channel, else the user of that name), c/<name> for a channel or user/<name> for a user, any channel or user link with any tab after it (rumble.com/c/Bongino, rumble.com/c/Bongino/videos, rumble.com/user/vivafrei/about, the root rumble.com/Bongino link), or a channel's id as this API returns it (_c276782) or its c/c-<channel id> name. A user's _u… id is refused: Rumble's public pages cannot look a user up by ID, so send its name. Names are case-insensitive.",
            "example": "Bongino",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Rumble channel or user: a bare name (Bongino: a channel, else the user of that name), c/<name> for a channel or user/<name> for a user, any channel or user link with any tab after it (rumble.com/c/Bongino, rumble.com/c/Bongino/videos, rumble.com/user/vivafrei/about, the root rumble.com/Bongino link), or a channel's id as this API returns it (_c276782) or its c/c-<channel id> name. A user's _u… id is refused: Rumble's public pages cannot look a user up by ID, so send its name. Names are case-insensitive.",
              "examples": [
                "Bongino"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "The uploads the figures cover: videos (default: the Videos tab), shorts, or live (Rumble's Livestreams tab: past streams, with the one on air and scheduled ones, whose counts are still growing). Many Rumble shows stream live, so their Livestreams tab is where most of their audience is.",
            "example": "live",
            "in": "query",
            "name": "tab",
            "schema": {
              "description": "The uploads the figures cover: videos (default: the Videos tab), shorts, or live (Rumble's Livestreams tab: past streams, with the one on air and scheduled ones, whose counts are still growing). Many Rumble shows stream live, so their Livestreams tab is where most of their audience is.",
              "enum": [
                "videos",
                "shorts",
                "live"
              ],
              "examples": [
                "live"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "bottom_post_id": "v7gad48",
                        "id": "_c276782",
                        "metrics": {
                          "comment_to_like_ratio": 0.30873,
                          "comments_per_post": 1314.88,
                          "counted_post_count": 25,
                          "engagement_rate": 0.001517,
                          "engagement_rate_stddev": 0.001491,
                          "formats": [
                            {
                              "counted_post_count": 25,
                              "engagement_rate": 0.001517,
                              "interactions_per_post": 5573.88,
                              "type": "video",
                              "views_per_post": 410657.28
                            }
                          ],
                          "interactions_per_post": 5573.88,
                          "likes_per_post": 4259,
                          "median_engagement_rate": 0.001104,
                          "median_views_per_post": 340453,
                          "posts_per_week": 0.24,
                          "quotes_per_post": null,
                          "rated_post_count": 25,
                          "reposts_per_post": 4,
                          "sampled_post_count": 25,
                          "saves_per_post": null,
                          "shares_per_post": null,
                          "view_engagement_rate": 0.011385,
                          "views_per_post": 410657.28
                        },
                        "newest_post_at": "2026-10-31T11:00:00Z",
                        "oldest_post_at": "2024-11-15T15:30:00Z",
                        "platform": "rumble",
                        "platform_specific": {},
                        "posts": [
                          {
                            "engagement_rate": 0.000292,
                            "engagement_vs_median": 0.26,
                            "is_counted": true,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": "https://hugh.cdn.rumble.cloud/video/z8/U/K/d/b/UKdba.baa.4-bongino-t8rqq7.jpeg",
                                "display_name": "The Dan Bongino Show",
                                "id": "_c276782",
                                "is_verified": true,
                                "url": "https://rumble.com/c/bongino",
                                "username": "bongino"
                              },
                              "coauthors": [],
                              "duration_ms": 3332000,
                              "hashtags": [],
                              "id": "v7hm5b6",
                              "is_nsfw": false,
                              "is_pinned": null,
                              "is_sponsored": null,
                              "language": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": 3332000,
                                  "expires_at": null,
                                  "height": 1080,
                                  "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fwe2/6a/s8/1/I/f/F/_/IfF_A.OvCc-small-Bongino-Weekend-Report-Week..jpg",
                                  "type": "video",
                                  "url": "https://hugh.cdn.rumble.cloud/video/fwe2/6a/s8/2/I/f/F/_/IfF_A.haa.mp4",
                                  "width": 1920
                                }
                              ],
                              "mentions": [],
                              "metrics": {
                                "comment_count": 82,
                                "like_count": 990,
                                "quote_count": null,
                                "repost_count": 0,
                                "save_count": null,
                                "share_count": null,
                                "view_count": 100545
                              },
                              "platform": "rumble",
                              "platform_specific": {
                                "rumble": {
                                  "author_follower_count": 3674175,
                                  "caption_tracks": [],
                                  "category": null,
                                  "concurrent_viewer_count": null,
                                  "dislike_count": 9,
                                  "embed_id": "v7ffsdo",
                                  "embed_url": "https://rumble.com/embed/v7ffsdo/",
                                  "files": [],
                                  "is_age_restricted": false,
                                  "is_live_now": false,
                                  "keywords": [],
                                  "live_started_at": null,
                                  "numeric_id": "449194092",
                                  "scheduled_start_at": null,
                                  "secondary_category": null
                                }
                              },
                              "platform_type": "video",
                              "published_at": "2026-10-31T11:00:00Z",
                              "text": null,
                              "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fwe2/6a/s8/1/I/f/F/_/IfF_A.OvCc-small-Bongino-Weekend-Report-Week..jpg",
                              "title": "Bongino Weekend Report - Week of 10/26/26",
                              "type": "video",
                              "unknown_fields": [
                                "hashtags",
                                "mentions",
                                "platform_specific.rumble.keywords"
                              ],
                              "url": "https://rumble.com/v7hm5b6-bongino-weekend-report-week-of-102626.html"
                            },
                            "view_engagement_rate": 0.010662,
                            "views_vs_median": 0.3
                          },
                          {
                            "engagement_rate": 0.000363,
                            "engagement_vs_median": 0.33,
                            "is_counted": true,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": "https://hugh.cdn.rumble.cloud/video/z8/U/K/d/b/UKdba.baa.4-bongino-t8rqq7.jpeg",
                                "display_name": "The Dan Bongino Show",
                                "id": "_c276782",
                                "is_verified": true,
                                "url": "https://rumble.com/c/bongino",
                                "username": "bongino"
                              },
                              "coauthors": [],
                              "duration_ms": 3233000,
                              "hashtags": [],
                              "id": "v7haadi",
                              "is_nsfw": false,
                              "is_pinned": null,
                              "is_sponsored": null,
                              "language": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": 3233000,
                                  "expires_at": null,
                                  "height": 1080,
                                  "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fww1/25/s8/1/g/a/y/9/gay9A.OvCc-small-Bongino-Weekend-Report-Week..jpg",
                                  "type": "video",
                                  "url": "https://hugh.cdn.rumble.cloud/video/fww1/25/s8/2/g/a/y/9/gay9A.haa.mp4",
                                  "width": 1920
                                }
                              ],
                              "mentions": [],
                              "metrics": {
                                "comment_count": 82,
                                "like_count": 1251,
                                "quote_count": null,
                                "repost_count": 3,
                                "save_count": null,
                                "share_count": null,
                                "view_count": 254011
                              },
                              "platform": "rumble",
                              "platform_specific": {
                                "rumble": {
                                  "author_follower_count": 3674175,
                                  "caption_tracks": [],
                                  "category": null,
                                  "concurrent_viewer_count": null,
                                  "dislike_count": 17,
                                  "embed_id": "v7f3xg0",
                                  "embed_url": "https://rumble.com/embed/v7f3xg0/",
                                  "files": [],
                                  "is_age_restricted": false,
                                  "is_live_now": false,
                                  "keywords": [],
                                  "live_started_at": null,
                                  "numeric_id": "448640784",
                                  "scheduled_start_at": null,
                                  "secondary_category": null
                                }
                              },
                              "platform_type": "video",
                              "published_at": "2026-10-24T11:01:00Z",
                              "text": null,
                              "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fww1/25/s8/1/g/a/y/9/gay9A.OvCc-small-Bongino-Weekend-Report-Week..jpg",
                              "title": "Bongino Weekend Report - Week of 10/19/26",
                              "type": "video",
                              "unknown_fields": [
                                "hashtags",
                                "mentions",
                                "platform_specific.rumble.keywords"
                              ],
                              "url": "https://rumble.com/v7haadi-bongino-weekend-report-week-of-101926.html"
                            },
                            "view_engagement_rate": 0.005248,
                            "views_vs_median": 0.75
                          },
                          {
                            "engagement_rate": 0.000354,
                            "engagement_vs_median": 0.32,
                            "is_counted": true,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": "https://hugh.cdn.rumble.cloud/video/z8/U/K/d/b/UKdba.baa.4-bongino-t8rqq7.jpeg",
                                "display_name": "The Dan Bongino Show",
                                "id": "_c276782",
                                "is_verified": true,
                                "url": "https://rumble.com/c/bongino",
                                "username": "bongino"
                              },
                              "coauthors": [],
                              "duration_ms": 3316000,
                              "hashtags": [],
                              "id": "v7gyjd4",
                              "is_nsfw": false,
                              "is_pinned": null,
                              "is_sponsored": null,
                              "language": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": 3316000,
                                  "expires_at": null,
                                  "height": 1080,
                                  "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fww1/bd/s8/1/i/k/s/7/iks7A.OvCc-small-Bongino-Weekend-Report-Week..jpg",
                                  "type": "video",
                                  "url": "https://hugh.cdn.rumble.cloud/video/fww1/bd/s8/2/i/k/s/7/iks7A.haa.mp4",
                                  "width": 1920
                                }
                              ],
                              "mentions": [],
                              "metrics": {
                                "comment_count": 120,
                                "like_count": 1180,
                                "quote_count": null,
                                "repost_count": 2,
                                "save_count": null,
                                "share_count": null,
                                "view_count": 265997
                              },
                              "platform": "rumble",
                              "platform_specific": {
                                "rumble": {
                                  "author_follower_count": 3674175,
                                  "caption_tracks": [],
                                  "category": null,
                                  "concurrent_viewer_count": null,
                                  "dislike_count": 25,
                                  "embed_id": "v7es6fm",
                                  "embed_url": "https://rumble.com/embed/v7es6fm/",
                                  "files": [],
                                  "is_age_restricted": false,
                                  "is_live_now": false,
                                  "keywords": [],
                                  "live_started_at": null,
                                  "numeric_id": "448092562",
                                  "scheduled_start_at": null,
                                  "secondary_category": null
                                }
                              },
                              "platform_type": "video",
                              "published_at": "2026-10-17T13:00:00Z",
                              "text": null,
                              "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fww1/bd/s8/1/i/k/s/7/iks7A.OvCc-small-Bongino-Weekend-Report-Week..jpg",
                              "title": "Bongino Weekend Report - Week of 10/12/26",
                              "type": "video",
                              "unknown_fields": [
                                "hashtags",
                                "mentions",
                                "platform_specific.rumble.keywords"
                              ],
                              "url": "https://rumble.com/v7gyjd4-bongino-weekend-report-week-of-101226.html"
                            },
                            "view_engagement_rate": 0.004887,
                            "views_vs_median": 0.78
                          }
                        ],
                        "profile": {
                          "approximate_fields": [
                            "created_at"
                          ],
                          "avatar_url": "https://hugh.cdn.rumble.cloud/video/z8/U/K/d/b/UKdba.baa.4-bongino-t8rqq7.jpeg",
                          "banner_url": "https://hugh.cdn.rumble.cloud/video/z8/U/K/d/b/UKdba.caa-bongino-tbhrxo.png",
                          "bio": "The official channel for The Dan Bongino Show®. A former Deputy Director of the FBI, Secret Service Agent, NYPD officer, and best-selling author, Dan Bongino tackles the hot political issues, debunking both liberal and Republican establishment rhetoric.",
                          "category": null,
                          "country_code": null,
                          "created_at": "2020-09-16T00:00:00Z",
                          "display_name": "The Dan Bongino Show",
                          "external_links": [
                            {
                              "title": "Twitter",
                              "url": "https://twitter.com/dbongino"
                            },
                            {
                              "title": "Facebook",
                              "url": "https://facebook.com/danbongino"
                            },
                            {
                              "title": "Instagram",
                              "url": "https://instagram.com/dbongino"
                            }
                          ],
                          "id": "_c276782",
                          "is_private": false,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": 3674175,
                            "following_count": null,
                            "post_count": 2150,
                            "total_like_count": null,
                            "total_view_count": 390223865
                          },
                          "platform": "rumble",
                          "platform_specific": {
                            "rumble": {
                              "account_type": "channel",
                              "numeric_id": "276782",
                              "user_id": "_u169h4"
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [],
                          "url": "https://rumble.com/c/bongino",
                          "username": "bongino"
                        },
                        "top_post_id": "v5pcynb",
                        "unknown_fields": [],
                        "url": "https://rumble.com/c/bongino"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "rumble",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 723,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "_c276782",
                          "url": "https://rumble.com/c/bongino"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RumbleEngagementResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Engagement rate from a channel's latest videos",
        "tags": [
          "Rumble"
        ],
        "x-socialtap-endpoint": "rumble.engagement",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "engagement",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/rumble/post": {
      "get": {
        "description": "Returns a public Rumble video, short or live stream from its link or ID, with views, likes, dislikes, title, description and channel. It also has the publish time, length, thumbnail, Rumble's categories and tags, every video and audio file with its size, and the caption tracks. A live stream says whether it is on air, when it started or is scheduled, and how many people are watching.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/rumble/post/ (Markdown: https://socialtap.dev/docs/reference/rumble/post/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/rumble/post/index.md)",
          "url": "https://socialtap.dev/docs/reference/rumble/post/"
        },
        "operationId": "rumble.post.get",
        "parameters": [
          {
            "description": "Rumble video, short or live stream URL (rumble.com/v…-title.html, /shorts/v…, /share/v…, /embed/v…/) or a video ID (v…).",
            "example": "https://rumble.com/v79xhhm-discovery-why-glenn-wants-israel-to-sue-the-new-york-times.html",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Rumble video, short or live stream URL (rumble.com/v…-title.html, /shorts/v…, /share/v…, /embed/v…/) or a video ID (v…).",
              "examples": [
                "https://rumble.com/v79xhhm-discovery-why-glenn-wants-israel-to-sue-the-new-york-times.html"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "platform_specific.rumble.author_follower_count"
                        ],
                        "author": {
                          "avatar_url": "https://hugh.cdn.rumble.cloud/video/z8/g/D/5/d/gD5da.baa.2-GGreenwald-rml416.png",
                          "display_name": "Glenn Greenwald",
                          "id": "_c1021766",
                          "is_verified": true,
                          "url": "https://rumble.com/c/GGreenwald",
                          "username": "GGreenwald"
                        },
                        "coauthors": [],
                        "duration_ms": 1678000,
                        "hashtags": [],
                        "id": "v79xhhm",
                        "is_nsfw": null,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": null,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": 1678000,
                            "expires_at": null,
                            "height": 1080,
                            "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fwe2/2f/s8/1/k/V/p/o/kVpoA.qR4e-small-DISCOVERY-Why-Glenn-WANTS-I..jpg",
                            "type": "video",
                            "url": "https://rumble.com/hls-vod/vjXafkcCce8/playlist.m3u8",
                            "width": 1920
                          }
                        ],
                        "mentions": [],
                        "metrics": {
                          "comment_count": 22,
                          "like_count": 209,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": null,
                          "share_count": null,
                          "view_count": 25366
                        },
                        "platform": "rumble",
                        "platform_specific": {
                          "rumble": {
                            "author_follower_count": 584000,
                            "caption_tracks": [
                              {
                                "is_auto_generated": true,
                                "label": "English (auto)",
                                "language": "en",
                                "url": "https://hugh.cdn.rumble.cloud/video/fwe2/2f/s8/11/k/V/p/o/kVpoA.fn8Si.1.vtt"
                              }
                            ],
                            "category": "News",
                            "concurrent_viewer_count": null,
                            "dislike_count": 4,
                            "embed_id": "v77qthe",
                            "embed_url": "https://rumble.com/embed/v77qthe/",
                            "files": [
                              {
                                "bitrate_kbps": 2142,
                                "format": "tar",
                                "height": 720,
                                "kind": "video",
                                "size_bytes": 449566720,
                                "url": "https://hugh.cdn.rumble.cloud/video/fwe2/2f/s8/2/k/V/p/o/kVpoA.gaa.tar?r_file=chunklist.m3u8&r_type=application%2Fvnd.apple.mpegurl&r_range=449539072-449555872",
                                "width": 1280
                              },
                              {
                                "bitrate_kbps": 1059,
                                "format": "tar",
                                "height": 480,
                                "kind": "video",
                                "size_bytes": 222300160,
                                "url": "https://hugh.cdn.rumble.cloud/video/fwe2/2f/s8/2/k/V/p/o/kVpoA.caa.tar?r_file=chunklist.m3u8&r_type=application%2Fvnd.apple.mpegurl&r_range=222280704-222297420",
                                "width": 854
                              },
                              {
                                "bitrate_kbps": 679,
                                "format": "tar",
                                "height": 360,
                                "kind": "video",
                                "size_bytes": 142510080,
                                "url": "https://hugh.cdn.rumble.cloud/video/fwe2/2f/s8/2/k/V/p/o/kVpoA.baa.tar?r_file=chunklist.m3u8&r_type=application%2Fvnd.apple.mpegurl&r_range=142485504-142502129",
                                "width": 640
                              }
                            ],
                            "is_age_restricted": null,
                            "is_live_now": false,
                            "keywords": [],
                            "live_started_at": null,
                            "numeric_id": "436271810",
                            "scheduled_start_at": null,
                            "secondary_category": "Politics"
                          }
                        },
                        "platform_type": "video",
                        "published_at": "2026-05-16T11:31:27Z",
                        "text": "Follow Glenn Greenwald's writing and other journalism at Substack, where you can become a member: https://greenwald.substack.com/\n\nAll videos now available as a podcast! Find full episodes here: https://linktr.ee/systemupdate_\n\nFollow Glenn:\nTwitter: https://twitter.com/ggreenwal…",
                        "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fwe2/2f/s8/1/k/V/p/o/kVpoA.qR4e-small-DISCOVERY-Why-Glenn-WANTS-I..jpg",
                        "title": "DISCOVERY: Why Glenn WANTS Israel to Sue The New York Times",
                        "type": "video",
                        "unknown_fields": [],
                        "url": "https://rumble.com/v79xhhm-discovery-why-glenn-wants-israel-to-sue-the-new-york-times.html"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "rumble",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 11766,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "v79xhhm",
                          "url": "https://rumble.com/v79xhhm-discovery-why-glenn-wants-israel-to-sue-the-new-york-times.html"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RumblePostResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Video, short or stream with views, likes and dislikes",
        "tags": [
          "Rumble"
        ],
        "x-socialtap-endpoint": "rumble.post",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/rumble/posts": {
      "get": {
        "description": "Returns a Rumble channel's or user's public videos, shorts or live streams a page at a time, newest or most viewed first. Each has its link, title, thumbnail, upload time, length, exact views, likes, dislikes, comments and reposts, the video file, and the channel with its exact follower count and badge. A live stream also says whether it is on air, how many are watching, and when it started or is due. Accepts a channel or user name, any channel or user link, or a channel ID.\n\nReturns `{data, page, meta}`: `data` holds up to 25 `Post` items (the shared schema, the same on every platform), Rumble's upload order (newest uploads first, not strictly by published_at) with sort=newest (the default), Rumble's View count order (most viewed first) with sort=popular. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/rumble/posts/ (Markdown: https://socialtap.dev/docs/reference/rumble/posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/rumble/posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/rumble/posts/"
        },
        "operationId": "rumble.posts.list",
        "parameters": [
          {
            "description": "Rumble channel or user: a bare name (Bongino: a channel, else the user of that name), c/<name> for a channel or user/<name> for a user, any channel or user link with any tab after it (rumble.com/c/Bongino, rumble.com/c/Bongino/shorts, rumble.com/user/vivafrei/livestreams, the root rumble.com/Bongino link), or a channel's id as this API returns it (_c276782) or its c/c-<channel id> name. A user's _u… id is refused: Rumble's public pages cannot look a user up by ID, so send its name. Names are case-insensitive.",
            "example": "Bongino",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Rumble channel or user: a bare name (Bongino: a channel, else the user of that name), c/<name> for a channel or user/<name> for a user, any channel or user link with any tab after it (rumble.com/c/Bongino, rumble.com/c/Bongino/shorts, rumble.com/user/vivafrei/livestreams, the root rumble.com/Bongino link), or a channel's id as this API returns it (_c276782) or its c/c-<channel id> name. A user's _u… id is refused: Rumble's public pages cannot look a user up by ID, so send its name. Names are case-insensitive.",
              "examples": [
                "Bongino"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "The tab to list: videos (default), shorts or live (Rumble's Livestreams tab: streams on air now, scheduled ones and past ones). A user's tabs include the videos of the channels it owns.",
            "example": "live",
            "in": "query",
            "name": "tab",
            "schema": {
              "description": "The tab to list: videos (default), shorts or live (Rumble's Livestreams tab: streams on air now, scheduled ones and past ones). A user's tabs include the videos of the channels it owns.",
              "enum": [
                "videos",
                "shorts",
                "live"
              ],
              "examples": [
                "live"
              ],
              "type": "string"
            }
          },
          {
            "description": "Order of the results. newest (default): Rumble's upload order, newest uploads first (Rumble's own order, not strictly by published_at: older uploads can sit among newer ones). popular: Rumble's View count order (most viewed first).",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "newest",
              "description": "Order of the results. newest (default): Rumble's upload order, newest uploads first (Rumble's own order, not strictly by published_at: older uploads can sit among newer ones). popular: Rumble's View count order (most viewed first).",
              "enum": [
                "newest",
                "popular"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Neither sort is strictly by date, so since filters every page instead of ending the walk at the first older post: the walk ends after a few pages in a row with nothing in the window, and those pages are free.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Neither sort is strictly by date, so since filters every page instead of ending the walk at the first older post: the walk ends after a few pages in a row with nothing in the window, and those pages are free.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Filters every page, like since.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Filters every page, like since.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only short videos (Rumble's Under 4 minutes) or long ones (Over 20 minutes); any length when omitted. Not with tab=shorts.",
            "example": "long",
            "in": "query",
            "name": "duration",
            "schema": {
              "description": "Only short videos (Rumble's Under 4 minutes) or long ones (Over 20 minutes); any length when omitted. Not with tab=shorts.",
              "enum": [
                "short",
                "long"
              ],
              "examples": [
                "long"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 25,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 25,
              "maximum": 25,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://hugh.cdn.rumble.cloud/video/z8/U/K/d/b/UKdba.baa.4-bongino-t8rqq7.jpeg",
                            "display_name": "The Dan Bongino Show",
                            "id": "_c276782",
                            "is_verified": true,
                            "url": "https://rumble.com/c/bongino",
                            "username": "bongino"
                          },
                          "coauthors": [],
                          "duration_ms": 3233000,
                          "hashtags": [],
                          "id": "v7haadi",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 3233000,
                              "expires_at": null,
                              "height": 1080,
                              "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fww1/25/s8/1/g/a/y/9/gay9A.OvCc-small-Bongino-Weekend-Report-Week..jpg",
                              "type": "video",
                              "url": "https://hugh.cdn.rumble.cloud/video/fww1/25/s8/2/g/a/y/9/gay9A.haa.mp4",
                              "width": 1920
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 80,
                            "like_count": 1182,
                            "quote_count": null,
                            "repost_count": 3,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 207825
                          },
                          "platform": "rumble",
                          "platform_specific": {
                            "rumble": {
                              "author_follower_count": 3673478,
                              "caption_tracks": [],
                              "category": null,
                              "concurrent_viewer_count": null,
                              "dislike_count": 13,
                              "embed_id": "v7f3xg0",
                              "embed_url": "https://rumble.com/embed/v7f3xg0/",
                              "files": [],
                              "is_age_restricted": false,
                              "is_live_now": false,
                              "keywords": [],
                              "live_started_at": null,
                              "numeric_id": "448640784",
                              "scheduled_start_at": null,
                              "secondary_category": null
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-24T11:01:00Z",
                          "text": null,
                          "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fww1/25/s8/1/g/a/y/9/gay9A.OvCc-small-Bongino-Weekend-Report-Week..jpg",
                          "title": "Bongino Weekend Report - Week of 10/19/26",
                          "type": "video",
                          "unknown_fields": [
                            "hashtags",
                            "mentions",
                            "platform_specific.rumble.keywords"
                          ],
                          "url": "https://rumble.com/v7haadi-bongino-weekend-report-week-of-101926.html"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://hugh.cdn.rumble.cloud/video/z8/U/K/d/b/UKdba.baa.4-bongino-t8rqq7.jpeg",
                            "display_name": "The Dan Bongino Show",
                            "id": "_c276782",
                            "is_verified": true,
                            "url": "https://rumble.com/c/bongino",
                            "username": "bongino"
                          },
                          "coauthors": [],
                          "duration_ms": 3316000,
                          "hashtags": [],
                          "id": "v7gyjd4",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 3316000,
                              "expires_at": null,
                              "height": 1080,
                              "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fww1/bd/s8/1/i/k/s/7/iks7A.OvCc-small-Bongino-Weekend-Report-Week..jpg",
                              "type": "video",
                              "url": "https://hugh.cdn.rumble.cloud/video/fww1/bd/s8/2/i/k/s/7/iks7A.haa.mp4",
                              "width": 1920
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 119,
                            "like_count": 1170,
                            "quote_count": null,
                            "repost_count": 2,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 257009
                          },
                          "platform": "rumble",
                          "platform_specific": {
                            "rumble": {
                              "author_follower_count": 3673478,
                              "caption_tracks": [],
                              "category": null,
                              "concurrent_viewer_count": null,
                              "dislike_count": 25,
                              "embed_id": "v7es6fm",
                              "embed_url": "https://rumble.com/embed/v7es6fm/",
                              "files": [],
                              "is_age_restricted": false,
                              "is_live_now": false,
                              "keywords": [],
                              "live_started_at": null,
                              "numeric_id": "448092562",
                              "scheduled_start_at": null,
                              "secondary_category": null
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-17T13:00:00Z",
                          "text": null,
                          "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fww1/bd/s8/1/i/k/s/7/iks7A.OvCc-small-Bongino-Weekend-Report-Week..jpg",
                          "title": "Bongino Weekend Report - Week of 10/12/26",
                          "type": "video",
                          "unknown_fields": [
                            "hashtags",
                            "mentions",
                            "platform_specific.rumble.keywords"
                          ],
                          "url": "https://rumble.com/v7gyjd4-bongino-weekend-report-week-of-101226.html"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://hugh.cdn.rumble.cloud/video/z8/U/K/d/b/UKdba.baa.4-bongino-t8rqq7.jpeg",
                            "display_name": "The Dan Bongino Show",
                            "id": "_c276782",
                            "is_verified": true,
                            "url": "https://rumble.com/c/bongino",
                            "username": "bongino"
                          },
                          "coauthors": [],
                          "duration_ms": 3350000,
                          "hashtags": [],
                          "id": "v7go45s",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 3350000,
                              "expires_at": null,
                              "height": 1080,
                              "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fwe2/2c/s8/1/q/C/B/5/qCB5A.OvCc-small-Bongino-Weekend-Report-Week..jpg",
                              "type": "video",
                              "url": "https://hugh.cdn.rumble.cloud/video/fwe2/2c/s8/2/q/C/B/5/qCB5A.haa.mp4",
                              "width": 1920
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 164,
                            "like_count": 1143,
                            "quote_count": null,
                            "repost_count": 0,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 265418
                          },
                          "platform": "rumble",
                          "platform_specific": {
                            "rumble": {
                              "author_follower_count": 3673477,
                              "caption_tracks": [],
                              "category": null,
                              "concurrent_viewer_count": null,
                              "dislike_count": 22,
                              "embed_id": "v7ehr8a",
                              "embed_url": "https://rumble.com/embed/v7ehr8a/",
                              "files": [],
                              "is_age_restricted": false,
                              "is_live_now": false,
                              "keywords": [],
                              "live_started_at": null,
                              "numeric_id": "447606298",
                              "scheduled_start_at": null,
                              "secondary_category": null
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-10T16:03:02Z",
                          "text": null,
                          "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fwe2/2c/s8/1/q/C/B/5/qCB5A.OvCc-small-Bongino-Weekend-Report-Week..jpg",
                          "title": "Bongino Weekend Report - Week of 10/05/26",
                          "type": "video",
                          "unknown_fields": [
                            "hashtags",
                            "mentions",
                            "platform_specific.rumble.keywords"
                          ],
                          "url": "https://rumble.com/v7go45s-bongino-weekend-report-week-of-100526.html"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "rumble",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 647,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "_c276782",
                          "url": "https://rumble.com/c/bongino"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RumblePostsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Videos, shorts and live streams of any channel",
        "tags": [
          "Rumble"
        ],
        "x-socialtap-endpoint": "rumble.posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "free_filtered_pages": true,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Rumble's upload order (newest uploads first, not strictly by published_at)",
          "orders": {
            "newest": "Rumble's upload order (newest uploads first, not strictly by published_at)",
            "popular": "Rumble's View count order (most viewed first)"
          },
          "page_max": 25,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/rumble/profile": {
      "get": {
        "description": "Returns a public Rumble channel or user profile from its name, link or channel ID, with its follower count and exact video and view counts. It also has Rumble's ID for the account (the one its videos name the uploader by), name, description, avatar, banner, verified badge, the social links it lists, its join date, and whether it is a channel or a user, with the user who owns it.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/rumble/profile/ (Markdown: https://socialtap.dev/docs/reference/rumble/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/rumble/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/rumble/profile/"
        },
        "operationId": "rumble.profile.get",
        "parameters": [
          {
            "description": "Rumble channel or user: a bare name (Bongino: a channel, else the user of that name), c/<name> for a channel or user/<name> for a user, any channel or user link with any tab after it (rumble.com/c/Bongino, rumble.com/c/Bongino/videos, rumble.com/user/vivafrei/about, the root rumble.com/Bongino link), or a channel's id as this API returns it (_c276782) or its c/c-<channel id> name (c/c-276782, which every channel has). A user's _u… id is refused: Rumble's public pages cannot look a user up by ID, so send its name. Names are case-insensitive.",
            "example": "Bongino",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Rumble channel or user: a bare name (Bongino: a channel, else the user of that name), c/<name> for a channel or user/<name> for a user, any channel or user link with any tab after it (rumble.com/c/Bongino, rumble.com/c/Bongino/videos, rumble.com/user/vivafrei/about, the root rumble.com/Bongino link), or a channel's id as this API returns it (_c276782) or its c/c-<channel id> name (c/c-276782, which every channel has). A user's _u… id is refused: Rumble's public pages cannot look a user up by ID, so send its name. Names are case-insensitive.",
              "examples": [
                "Bongino"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "metrics.follower_count",
                          "created_at"
                        ],
                        "avatar_url": "https://hugh.cdn.rumble.cloud/video/z8/U/K/d/b/UKdba.baa.4-bongino-t8rqq7.jpeg",
                        "banner_url": "https://hugh.cdn.rumble.cloud/video/z8/U/K/d/b/UKdba.caa-bongino-tbhrxo.png",
                        "bio": "The official channel for The Dan Bongino Show®. A former Deputy Director of the FBI, Secret Service Agent, NYPD officer, and best-selling author, Dan Bongino tackles the hot political issues, debunking both liberal and Republican establishment rhetoric.",
                        "category": null,
                        "country_code": null,
                        "created_at": "2020-09-16T00:00:00Z",
                        "display_name": "The Dan Bongino Show",
                        "external_links": [
                          {
                            "title": "Twitter",
                            "url": "https://twitter.com/dbongino"
                          },
                          {
                            "title": "Facebook",
                            "url": "https://facebook.com/danbongino"
                          },
                          {
                            "title": "Instagram",
                            "url": "https://instagram.com/dbongino"
                          }
                        ],
                        "id": "_c276782",
                        "is_private": false,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 3670000,
                          "following_count": null,
                          "post_count": 2136,
                          "total_like_count": null,
                          "total_view_count": 389354965
                        },
                        "platform": "rumble",
                        "platform_specific": {
                          "rumble": {
                            "account_type": "channel",
                            "numeric_id": "276782",
                            "user_id": "_u169h4"
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://rumble.com/c/bongino",
                        "username": "bongino"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "rumble",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 394,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "_c276782",
                          "url": "https://rumble.com/c/bongino"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RumbleProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Follower, video and view counts of channels and users",
        "tags": [
          "Rumble"
        ],
        "x-socialtap-endpoint": "rumble.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/rumble/search_posts": {
      "get": {
        "description": "Searches Rumble's public videos and live streams, or its shorts, by keyword, ranked by relevance, newest or most viewed, a page at a time. Each result has its link, title, thumbnail, upload time, length, views, likes, dislikes and comments, its channel with the verified badge, and whether a stream is on air with its viewer count. Shorts also have exact counts, the channel's follower count and the video file. Filter by upload date and length with Rumble's own filters.\n\nReturns `{data, page, meta}`: `data` holds up to 36 `Post` items (the shared schema, the same on every platform), Rumble's relevance order with sort=relevance (the default), newest first with sort=newest, Rumble's View count order (most viewed first) with sort=popular. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/rumble/search_posts/ (Markdown: https://socialtap.dev/docs/reference/rumble/search_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/rumble/search_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/rumble/search_posts/"
        },
        "operationId": "rumble.search_posts.list",
        "parameters": [
          {
            "description": "Keywords, matched by Rumble's search against titles and channels.",
            "example": "cats",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Keywords, matched by Rumble's search against titles and channels.",
              "examples": [
                "cats"
              ],
              "maxLength": 512,
              "type": "string"
            }
          },
          {
            "description": "The search tab to list: videos (default; videos and live streams) or shorts.",
            "example": "shorts",
            "in": "query",
            "name": "tab",
            "schema": {
              "description": "The search tab to list: videos (default; videos and live streams) or shorts.",
              "enum": [
                "videos",
                "shorts"
              ],
              "examples": [
                "shorts"
              ],
              "type": "string"
            }
          },
          {
            "description": "Order of the results. relevance (default): Rumble's best match. newest: newest uploads first. popular: Rumble's View count order (most viewed first).",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "relevance",
              "description": "Order of the results. relevance (default): Rumble's best match. newest: newest uploads first. popular: Rumble's View count order (most viewed first).",
              "enum": [
                "relevance",
                "newest",
                "popular"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Rumble's upload-date filter is applied when it covers since (the last day, week, month or year), so fewer pages are fetched.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Rumble's upload-date filter is applied when it covers since (the last day, week, month or year), so fewer pages are fetched.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only short videos (Rumble's Under 4 minutes) or long ones (Over 20 minutes). Any length when omitted.",
            "example": "long",
            "in": "query",
            "name": "duration",
            "schema": {
              "description": "Only short videos (Rumble's Under 4 minutes) or long ones (Over 20 minutes). Any length when omitted.",
              "enum": [
                "short",
                "long"
              ],
              "examples": [
                "long"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 36,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 36,
              "maximum": 36,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": null,
                            "display_name": "ViralHog",
                            "id": "_u7bbl",
                            "is_verified": false,
                            "url": "https://rumble.com/user/ViralHog",
                            "username": "user/ViralHog"
                          },
                          "coauthors": [],
                          "duration_ms": 28000,
                          "hashtags": [],
                          "id": "v7hfhey",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 28000,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fww1/39/s8/6/Q/l/t/-/Qlt-A.oq1b.jpg",
                              "type": "video",
                              "url": null,
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 3,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 254
                          },
                          "platform": "rumble",
                          "platform_specific": {
                            "rumble": {
                              "author_follower_count": null,
                              "caption_tracks": [],
                              "category": null,
                              "concurrent_viewer_count": null,
                              "dislike_count": 0,
                              "embed_id": null,
                              "embed_url": null,
                              "files": [],
                              "is_age_restricted": null,
                              "is_live_now": false,
                              "keywords": [],
                              "live_started_at": null,
                              "numeric_id": null,
                              "scheduled_start_at": null,
                              "secondary_category": null
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-26T19:34:46Z",
                          "text": null,
                          "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fww1/39/s8/6/Q/l/t/-/Qlt-A.oq1b.jpg",
                          "title": "Orange Cat Sits Like Human On Fuzzy Couch",
                          "type": "video",
                          "unknown_fields": [
                            "hashtags",
                            "mentions",
                            "platform_specific.rumble.keywords"
                          ],
                          "url": "https://rumble.com/v7hfhey-orange-cat-sits-like-human-on-fuzzy-couch.html"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": null,
                            "display_name": "SereneChristine",
                            "id": "_urv80h",
                            "is_verified": false,
                            "url": "https://rumble.com/user/SereneChristine",
                            "username": "user/SereneChristine"
                          },
                          "coauthors": [],
                          "duration_ms": 932000,
                          "hashtags": [],
                          "id": "v7hdue2",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 932000,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fwe2/1e/s8/1/A/G/a/-/AGa-A.oq1b-small-The-Book-of-Enoch-Reveals-W..jpg",
                              "type": "video",
                              "url": null,
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 4,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 400
                          },
                          "platform": "rumble",
                          "platform_specific": {
                            "rumble": {
                              "author_follower_count": null,
                              "caption_tracks": [],
                              "category": null,
                              "concurrent_viewer_count": null,
                              "dislike_count": 1,
                              "embed_id": null,
                              "embed_url": null,
                              "files": [],
                              "is_age_restricted": null,
                              "is_live_now": false,
                              "keywords": [],
                              "live_started_at": null,
                              "numeric_id": null,
                              "scheduled_start_at": null,
                              "secondary_category": null
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-25T20:04:50Z",
                          "text": null,
                          "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fwe2/1e/s8/1/A/G/a/-/AGa-A.oq1b-small-The-Book-of-Enoch-Reveals-W..jpg",
                          "title": "The Book of Enoch Reveals Why Cats Were Sent to Earth — And Why the Church Removed That Chapter",
                          "type": "video",
                          "unknown_fields": [
                            "hashtags",
                            "mentions",
                            "platform_specific.rumble.keywords"
                          ],
                          "url": "https://rumble.com/v7hdue2-the-book-of-enoch-reveals-why-cats-were-sent-to-earth-and-why-the-church-re.html"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": null,
                            "display_name": "tubewatch1",
                            "id": "_utpvcv",
                            "is_verified": false,
                            "url": "https://rumble.com/user/tubewatch1",
                            "username": "user/tubewatch1"
                          },
                          "coauthors": [],
                          "duration_ms": 100000,
                          "hashtags": [],
                          "id": "v7hhiau",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 100000,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fww1/03/s8/6/M/p/Q/-/MpQ-A.oq1b.jpg",
                              "type": "video",
                              "url": null,
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 1,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 211
                          },
                          "platform": "rumble",
                          "platform_specific": {
                            "rumble": {
                              "author_follower_count": null,
                              "caption_tracks": [],
                              "category": null,
                              "concurrent_viewer_count": null,
                              "dislike_count": null,
                              "embed_id": null,
                              "embed_url": null,
                              "files": [],
                              "is_age_restricted": null,
                              "is_live_now": false,
                              "keywords": [],
                              "live_started_at": null,
                              "numeric_id": null,
                              "scheduled_start_at": null,
                              "secondary_category": null
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-27T22:19:31Z",
                          "text": null,
                          "thumbnail_url": "https://hugh.cdn.rumble.cloud/video/fww1/03/s8/6/M/p/Q/-/MpQ-A.oq1b.jpg",
                          "title": "Pretty Peaceful Precious Piper - My Adopted Shelter Cat Vlog",
                          "type": "video",
                          "unknown_fields": [
                            "hashtags",
                            "mentions",
                            "platform_specific.rumble.keywords"
                          ],
                          "url": "https://rumble.com/v7hhiau-pretty-peaceful-precious-piper-my-adopted-shelter-cat-vlog.html"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "rumble",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 4348,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RumbleSearch_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Videos, shorts and live streams for any keyword",
        "tags": [
          "Rumble"
        ],
        "x-socialtap-endpoint": "rumble.search_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Rumble's relevance order",
          "orders": {
            "newest": "newest first",
            "popular": "Rumble's View count order (most viewed first)",
            "relevance": "Rumble's relevance order"
          },
          "page_max": 36,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/rumble/transcript": {
      "get": {
        "description": "Returns the timed transcript of a public Rumble video, short or past live stream, from its captions or, when it has none, its audio. Each segment has its start and end time, and text holds the whole transcript. The uploader's captions win over Rumble's automatic ones; the answer names the track it used, links its WebVTT file and lists every track the video has. Accepts any Rumble video link, embed links included, or a video ID.\n\nReturns `{data, meta}`: `data` is a `Transcript` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit (captions) or 2 credits + 2 per started minute of media (speech-to-text) per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/rumble/transcript/ (Markdown: https://socialtap.dev/docs/reference/rumble/transcript/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/rumble/transcript/index.md)",
          "url": "https://socialtap.dev/docs/reference/rumble/transcript/"
        },
        "operationId": "rumble.transcript.get",
        "parameters": [
          {
            "description": "Rumble video, short or live stream URL (rumble.com/v…-title.html, /shorts/v…, /share/v…, /embed/v…/) or a video ID (v…).",
            "example": "https://rumble.com/v79xhhm-discovery-why-glenn-wants-israel-to-sue-the-new-york-times.html",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Rumble video, short or live stream URL (rumble.com/v…-title.html, /shorts/v…, /share/v…, /embed/v…/) or a video ID (v…).",
              "examples": [
                "https://rumble.com/v79xhhm-discovery-why-glenn-wants-israel-to-sue-the-new-york-times.html"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). Selects the caption track: an uploaded track in that language before Rumble's automatic one. When the video has no track in that language, the default track is returned (language says which). Default: an uploaded track in the spoken language, else Rumble's automatic captions.",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). Selects the caption track: an uploaded track in that language before Rumble's automatic one. When the video has no track in that language, the default track is returned (language says which). Default: an uploaded track in the spoken language, else Rumble's automatic captions.",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "available_languages": [
                          "en"
                        ],
                        "duration_ms": 1678000,
                        "id": "v79xhhm",
                        "is_auto_generated": true,
                        "language": "en",
                        "platform": "rumble",
                        "platform_specific": {
                          "rumble": {
                            "caption_tracks": [
                              {
                                "is_auto_generated": true,
                                "label": "English (auto)",
                                "language": "en",
                                "url": "https://hugh.cdn.rumble.cloud/video/fwe2/2f/s8/11/k/V/p/o/kVpoA.fn8Si.1.vtt"
                              }
                            ],
                            "caption_url": "https://hugh.cdn.rumble.cloud/video/fwe2/2f/s8/11/k/V/p/o/kVpoA.fn8Si.1.vtt",
                            "track_label": "English (auto)"
                          }
                        },
                        "segments": [
                          {
                            "end_ms": 11030,
                            "start_ms": 6830,
                            "text": "Let's get into these questions, and we'll try and get through as many as we can."
                          },
                          {
                            "end_ms": 15630,
                            "start_ms": 11030,
                            "text": "The first one is from Christi Marbet, who says there were a few questions about this."
                          },
                          {
                            "end_ms": 17730,
                            "start_ms": 15630,
                            "text": "They want you to comment on the following, quote,"
                          }
                        ],
                        "source": "captions",
                        "text": "Let's get into these questions, and we'll try and get through as many as we can. The first one is from Christi Marbet, who says there were a few questions about this. They want you to comment on the following, quote, the Christoph piece on Palestinian rape in Israel, and its supp…",
                        "url": "https://rumble.com/v79xhhm-discovery-why-glenn-wants-israel-to-sue-the-new-york-times.html"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "rumble",
                        "source": "captions",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 417,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "v79xhhm",
                          "url": "https://rumble.com/v79xhhm-discovery-why-glenn-wants-israel-to-sue-the-new-york-times.html"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/RumbleTranscriptResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "no_transcript": {
                    "$ref": "#/components/examples/no_transcript"
                  },
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.\n\n`no_transcript`: The video or audio exists but has no transcript: no caption track and no speech to transcribe. Do not retry. If the platform offers other languages, try one with lang.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Timed transcript of any video or past stream",
        "tags": [
          "Rumble"
        ],
        "x-socialtap-endpoint": "rumble.transcript",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 122,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "captions"
            },
            {
              "credits": 2,
              "label": "2 credits + 2 per started minute of media",
              "max": 122,
              "per": 2,
              "source": "asr",
              "unit": "media_minute",
              "unit_max": 60
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "transcript",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/security_events": {
      "get": {
        "description": "The signed-in person's sign-ins, failed sign-ins, password, email, two-factor and session changes, newest first, with the network and browser each came from. Kept `security_events_retention_s` (90 days). Free.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "security_events.list",
        "parameters": [
          {
            "description": "Events per page (default and maximum 100).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page; omit to start from the newest.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "created_at": {
                            "description": "When it happened, RFC 3339 UTC.",
                            "format": "date-time",
                            "type": "string"
                          },
                          "id": {
                            "description": "Event ID (sev_…).",
                            "type": "string"
                          },
                          "method": {
                            "description": "How, where it applies: password, google, github, totp or backup_code.",
                            "maxLength": 32,
                            "type": "string"
                          },
                          "network": {
                            "description": "The network it came from: the client's IPv4 address or IPv6 /64.",
                            "type": "string"
                          },
                          "object": {
                            "description": "Always security_event.",
                            "enum": [
                              "security_event"
                            ],
                            "type": "string"
                          },
                          "type": {
                            "description": "What happened.",
                            "enum": [
                              "sign_in",
                              "sign_in_failed",
                              "sign_up",
                              "email_verified",
                              "password_reset",
                              "password_changed",
                              "email_changed",
                              "provider_linked",
                              "provider_unlinked",
                              "two_factor_enabled",
                              "two_factor_disabled",
                              "two_factor_failed",
                              "session_revoked",
                              "sign_out",
                              "unproven_access_revoked",
                              "sign_up_declined",
                              "account_deletion_requested",
                              "account_deletion_canceled",
                              "agent_approved"
                            ],
                            "type": "string"
                          },
                          "user_agent": {
                            "description": "The browser's user agent, at most 256 characters.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "object",
                          "id",
                          "type",
                          "network",
                          "user_agent",
                          "created_at"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List sign-in and security events",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "List sign-in and security events",
        "tags": [
          "Signup"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/session": {
      "delete": {
        "description": "Ends the session and clears its cookie.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "session.delete",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "account_id": {
                          "description": "The account this session acts on: the one x-account-id named, else the person's own.",
                          "type": "string"
                        },
                        "accounts": {
                          "description": "Every account the signed-in person belongs to, their own first, then by when they joined: send one's account_id as x-account-id to act on it.",
                          "items": {
                            "properties": {
                              "account_id": {
                                "description": "The account (acct_…): send it as x-account-id to act on it.",
                                "type": "string"
                              },
                              "deletes_at": {
                                "description": "When the account is deleted for good, RFC 3339 UTC: its owner asked to delete it, and starting the dashboard on it (POST /v1/session with x-account-id) cancels that. null when it isn't being deleted.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "joined_at": {
                                "description": "When they joined it, RFC 3339 UTC.",
                                "format": "date-time",
                                "type": "string"
                              },
                              "object": {
                                "description": "Always account_membership.",
                                "enum": [
                                  "account_membership"
                                ],
                                "type": "string"
                              },
                              "owner_email": {
                                "description": "Its owner's address, which names it.",
                                "type": "string"
                              },
                              "role": {
                                "description": "The person's role in it.",
                                "enum": [
                                  "owner",
                                  "admin",
                                  "member"
                                ],
                                "type": "string"
                              }
                            },
                            "required": [
                              "object",
                              "account_id",
                              "owner_email",
                              "role",
                              "joined_at",
                              "deletes_at"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "activated_key_ids": {
                          "description": "IDs of the agent's pending live keys this call activated (agent_token); [] otherwise.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "credits_granted": {
                          "description": "Free credits this call granted (once per account); 0 otherwise.",
                          "type": "integer"
                        },
                        "deletion_canceled_at": {
                          "description": "When signing in last canceled this account's scheduled deletion (its API keys stayed revoked: create new ones), RFC 3339 UTC; null when it never was.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "email": {
                          "description": "The signed-in person's verified email address.",
                          "type": "string"
                        },
                        "expires_at": {
                          "description": "When the session ends, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "free_credits_skipped": {
                          "description": "Why the account this session acts on has no free credits (Account.free_credits_skipped), for its owner; null otherwise.",
                          "enum": [
                            "disposable_address",
                            "domain_daily_limit",
                            "network_daily_limit",
                            "mailbox_used"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "fresh_until": {
                          "description": "Until when this session may create API keys and change keys without re-verifying (password or two-factor code), RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "new_api_keys": {
                          "description": "Keys this call created, with their secrets shown only here (a new account's first key, the first time its dashboard starts); [] otherwise.",
                          "items": {
                            "properties": {
                              "created_at": {
                                "description": "When the key was created, RFC 3339 UTC.",
                                "format": "date-time",
                                "type": "string"
                              },
                              "created_by_key": {
                                "description": "The API key (key_…) that last created this key, gave it the admin scope or rotated it: revoking that key also revokes this one if this one has admin. Null when none did, or a person has rotated it in the dashboard since.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "created_by_user": {
                                "description": "The person (GET /v1/members user_id) who created this key in the dashboard, or whose key created it. They may have left the account since. Null when no person did (an operator, or a key from before this was recorded).",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "dashboard": {
                                "description": "true for the account's built-in dashboard key: the dashboard's playground runs as it (so its requests are logged, counted and billed like any key's). Nobody holds its secret, so it works only from the signed-in dashboard. Only its spend_limit can be changed (to cap what the playground spends live); renaming, rescoping, restricting, rotating or revoking it is forbidden (details.reason dashboard_key). It is made on first use and revoked with the account.",
                                "type": "boolean"
                              },
                              "expires_at": {
                                "description": "When the key stops working, RFC 3339 UTC; null when it never expires.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "id": {
                                "description": "Key ID (key_…): manage the key with it. It is not the secret.",
                                "type": "string"
                              },
                              "ip_allowlist": {
                                "description": "IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; [] = any.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "last_used_at": {
                                "description": "About when the key was last used (updated at most hourly); null when never.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "name": {
                                "description": "Your label for the key.",
                                "type": "string"
                              },
                              "object": {
                                "description": "Always api_key.",
                                "enum": [
                                  "api_key"
                                ],
                                "type": "string"
                              },
                              "prefix": {
                                "description": "The secret's first characters, to recognize it.",
                                "type": "string"
                              },
                              "previous_secret_expires_at": {
                                "description": "Until then the secret this key had before its last rotation works too (rotate_secret), RFC 3339 UTC; null when none does.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "revoked_at": {
                                "description": "When the key was revoked; null while it is not.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "scopes": {
                                "description": "What the key may call: endpoints (data endpoints), jobs (create, read and cancel jobs; includes jobs:read), jobs:read (read jobs and their results), account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).",
                                "items": {
                                  "enum": [
                                    "endpoints",
                                    "jobs",
                                    "jobs:read",
                                    "account:read",
                                    "admin"
                                  ],
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "secret": {
                                "description": "The key itself: send it in the x-api-key header. Shown only once: store it now.",
                                "type": "string"
                              },
                              "spend_limit": {
                                "description": "The key's spend limit and what it used this interval; null when the key has none.",
                                "properties": {
                                  "amount": {
                                    "description": "Most credits the key may spend per interval.",
                                    "type": "integer"
                                  },
                                  "interval": {
                                    "description": "Calendar day or month, UTC.",
                                    "enum": [
                                      "day",
                                      "month"
                                    ],
                                    "type": "string"
                                  },
                                  "resets_at": {
                                    "description": "Start of the next interval, RFC 3339 UTC.",
                                    "format": "date-time",
                                    "type": "string"
                                  },
                                  "used": {
                                    "description": "Credits the key spent this interval, plus what its requests in flight hold.",
                                    "type": "integer"
                                  }
                                },
                                "required": [
                                  "amount",
                                  "interval",
                                  "used",
                                  "resets_at"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              },
                              "status": {
                                "description": "pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.",
                                "enum": [
                                  "active",
                                  "pending",
                                  "expired",
                                  "revoked"
                                ],
                                "type": "string"
                              }
                            },
                            "required": [
                              "object",
                              "id",
                              "name",
                              "status",
                              "prefix",
                              "scopes",
                              "spend_limit",
                              "expires_at",
                              "ip_allowlist",
                              "created_at",
                              "last_used_at",
                              "revoked_at",
                              "dashboard",
                              "previous_secret_expires_at",
                              "created_by_key",
                              "created_by_user",
                              "secret"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "object": {
                          "description": "Always session.",
                          "enum": [
                            "session"
                          ],
                          "type": "string"
                        },
                        "role": {
                          "description": "The signed-in person's role in this account (account_id): what the dashboard lets them do here.",
                          "enum": [
                            "owner",
                            "admin",
                            "member"
                          ],
                          "type": "string"
                        },
                        "setup_required": {
                          "description": "Whether POST /v1/session still has this account's setting up to do: a new account's first key (its secret in its answer, once), or the decision on an agent-made account. False in POST /v1/session's own answer once it has done it.",
                          "type": "boolean"
                        },
                        "two_factor_enabled": {
                          "description": "Whether the signed-in person has two-factor authentication on.",
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "object",
                        "account_id",
                        "email",
                        "expires_at",
                        "new_api_keys",
                        "activated_key_ids",
                        "credits_granted",
                        "free_credits_skipped",
                        "two_factor_enabled",
                        "fresh_until",
                        "role",
                        "accounts",
                        "deletion_canceled_at",
                        "setup_required"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Sign out",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Sign out",
        "tags": [
          "Signup"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "get": {
        "description": "The signed-in person and account of the session cookie.\n\n**Auth:** the dashboard session cookie.",
        "operationId": "session.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "account_id": {
                          "description": "The account this session acts on: the one x-account-id named, else the person's own.",
                          "type": "string"
                        },
                        "accounts": {
                          "description": "Every account the signed-in person belongs to, their own first, then by when they joined: send one's account_id as x-account-id to act on it.",
                          "items": {
                            "properties": {
                              "account_id": {
                                "description": "The account (acct_…): send it as x-account-id to act on it.",
                                "type": "string"
                              },
                              "deletes_at": {
                                "description": "When the account is deleted for good, RFC 3339 UTC: its owner asked to delete it, and starting the dashboard on it (POST /v1/session with x-account-id) cancels that. null when it isn't being deleted.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "joined_at": {
                                "description": "When they joined it, RFC 3339 UTC.",
                                "format": "date-time",
                                "type": "string"
                              },
                              "object": {
                                "description": "Always account_membership.",
                                "enum": [
                                  "account_membership"
                                ],
                                "type": "string"
                              },
                              "owner_email": {
                                "description": "Its owner's address, which names it.",
                                "type": "string"
                              },
                              "role": {
                                "description": "The person's role in it.",
                                "enum": [
                                  "owner",
                                  "admin",
                                  "member"
                                ],
                                "type": "string"
                              }
                            },
                            "required": [
                              "object",
                              "account_id",
                              "owner_email",
                              "role",
                              "joined_at",
                              "deletes_at"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "activated_key_ids": {
                          "description": "IDs of the agent's pending live keys this call activated (agent_token); [] otherwise.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "credits_granted": {
                          "description": "Free credits this call granted (once per account); 0 otherwise.",
                          "type": "integer"
                        },
                        "deletion_canceled_at": {
                          "description": "When signing in last canceled this account's scheduled deletion (its API keys stayed revoked: create new ones), RFC 3339 UTC; null when it never was.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "email": {
                          "description": "The signed-in person's verified email address.",
                          "type": "string"
                        },
                        "expires_at": {
                          "description": "When the session ends, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "free_credits_skipped": {
                          "description": "Why the account this session acts on has no free credits (Account.free_credits_skipped), for its owner; null otherwise.",
                          "enum": [
                            "disposable_address",
                            "domain_daily_limit",
                            "network_daily_limit",
                            "mailbox_used"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "fresh_until": {
                          "description": "Until when this session may create API keys and change keys without re-verifying (password or two-factor code), RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "new_api_keys": {
                          "description": "Keys this call created, with their secrets shown only here (a new account's first key, the first time its dashboard starts); [] otherwise.",
                          "items": {
                            "properties": {
                              "created_at": {
                                "description": "When the key was created, RFC 3339 UTC.",
                                "format": "date-time",
                                "type": "string"
                              },
                              "created_by_key": {
                                "description": "The API key (key_…) that last created this key, gave it the admin scope or rotated it: revoking that key also revokes this one if this one has admin. Null when none did, or a person has rotated it in the dashboard since.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "created_by_user": {
                                "description": "The person (GET /v1/members user_id) who created this key in the dashboard, or whose key created it. They may have left the account since. Null when no person did (an operator, or a key from before this was recorded).",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "dashboard": {
                                "description": "true for the account's built-in dashboard key: the dashboard's playground runs as it (so its requests are logged, counted and billed like any key's). Nobody holds its secret, so it works only from the signed-in dashboard. Only its spend_limit can be changed (to cap what the playground spends live); renaming, rescoping, restricting, rotating or revoking it is forbidden (details.reason dashboard_key). It is made on first use and revoked with the account.",
                                "type": "boolean"
                              },
                              "expires_at": {
                                "description": "When the key stops working, RFC 3339 UTC; null when it never expires.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "id": {
                                "description": "Key ID (key_…): manage the key with it. It is not the secret.",
                                "type": "string"
                              },
                              "ip_allowlist": {
                                "description": "IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; [] = any.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "last_used_at": {
                                "description": "About when the key was last used (updated at most hourly); null when never.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "name": {
                                "description": "Your label for the key.",
                                "type": "string"
                              },
                              "object": {
                                "description": "Always api_key.",
                                "enum": [
                                  "api_key"
                                ],
                                "type": "string"
                              },
                              "prefix": {
                                "description": "The secret's first characters, to recognize it.",
                                "type": "string"
                              },
                              "previous_secret_expires_at": {
                                "description": "Until then the secret this key had before its last rotation works too (rotate_secret), RFC 3339 UTC; null when none does.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "revoked_at": {
                                "description": "When the key was revoked; null while it is not.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "scopes": {
                                "description": "What the key may call: endpoints (data endpoints), jobs (create, read and cancel jobs; includes jobs:read), jobs:read (read jobs and their results), account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).",
                                "items": {
                                  "enum": [
                                    "endpoints",
                                    "jobs",
                                    "jobs:read",
                                    "account:read",
                                    "admin"
                                  ],
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "secret": {
                                "description": "The key itself: send it in the x-api-key header. Shown only once: store it now.",
                                "type": "string"
                              },
                              "spend_limit": {
                                "description": "The key's spend limit and what it used this interval; null when the key has none.",
                                "properties": {
                                  "amount": {
                                    "description": "Most credits the key may spend per interval.",
                                    "type": "integer"
                                  },
                                  "interval": {
                                    "description": "Calendar day or month, UTC.",
                                    "enum": [
                                      "day",
                                      "month"
                                    ],
                                    "type": "string"
                                  },
                                  "resets_at": {
                                    "description": "Start of the next interval, RFC 3339 UTC.",
                                    "format": "date-time",
                                    "type": "string"
                                  },
                                  "used": {
                                    "description": "Credits the key spent this interval, plus what its requests in flight hold.",
                                    "type": "integer"
                                  }
                                },
                                "required": [
                                  "amount",
                                  "interval",
                                  "used",
                                  "resets_at"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              },
                              "status": {
                                "description": "pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.",
                                "enum": [
                                  "active",
                                  "pending",
                                  "expired",
                                  "revoked"
                                ],
                                "type": "string"
                              }
                            },
                            "required": [
                              "object",
                              "id",
                              "name",
                              "status",
                              "prefix",
                              "scopes",
                              "spend_limit",
                              "expires_at",
                              "ip_allowlist",
                              "created_at",
                              "last_used_at",
                              "revoked_at",
                              "dashboard",
                              "previous_secret_expires_at",
                              "created_by_key",
                              "created_by_user",
                              "secret"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "object": {
                          "description": "Always session.",
                          "enum": [
                            "session"
                          ],
                          "type": "string"
                        },
                        "role": {
                          "description": "The signed-in person's role in this account (account_id): what the dashboard lets them do here.",
                          "enum": [
                            "owner",
                            "admin",
                            "member"
                          ],
                          "type": "string"
                        },
                        "setup_required": {
                          "description": "Whether POST /v1/session still has this account's setting up to do: a new account's first key (its secret in its answer, once), or the decision on an agent-made account. False in POST /v1/session's own answer once it has done it.",
                          "type": "boolean"
                        },
                        "two_factor_enabled": {
                          "description": "Whether the signed-in person has two-factor authentication on.",
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "object",
                        "account_id",
                        "email",
                        "expires_at",
                        "new_api_keys",
                        "activated_key_ids",
                        "credits_granted",
                        "free_credits_skipped",
                        "two_factor_enabled",
                        "fresh_until",
                        "role",
                        "accounts",
                        "deletion_canceled_at",
                        "setup_required"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get the dashboard session",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Get the dashboard session",
        "tags": [
          "Signup"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "post": {
        "description": "The dashboard calls it once it is signed in (people sign in with Google, GitHub or an email address and password on the sign-in page). The first call of a new account returns its first API key (its secret shown only here); with agent_token, it approves that agent signup, activating the agent's pending live key and granting the free credits. An account an agent opened that its owner signs in to without approving the agent gets fresh keys, and the agent's are revoked. Free.\n\n**Auth:** the dashboard session cookie.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "session.create",
        "parameters": [
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "agent_token": {
                    "description": "An agent signup's confirmation token (after # on the agent confirmation page): approves that agent, activating its pending live key. Only the signed-in owner of the address the agent named can use it.",
                    "maxLength": 200,
                    "minLength": 16,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "account_id": {
                          "description": "The account this session acts on: the one x-account-id named, else the person's own.",
                          "type": "string"
                        },
                        "accounts": {
                          "description": "Every account the signed-in person belongs to, their own first, then by when they joined: send one's account_id as x-account-id to act on it.",
                          "items": {
                            "properties": {
                              "account_id": {
                                "description": "The account (acct_…): send it as x-account-id to act on it.",
                                "type": "string"
                              },
                              "deletes_at": {
                                "description": "When the account is deleted for good, RFC 3339 UTC: its owner asked to delete it, and starting the dashboard on it (POST /v1/session with x-account-id) cancels that. null when it isn't being deleted.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "joined_at": {
                                "description": "When they joined it, RFC 3339 UTC.",
                                "format": "date-time",
                                "type": "string"
                              },
                              "object": {
                                "description": "Always account_membership.",
                                "enum": [
                                  "account_membership"
                                ],
                                "type": "string"
                              },
                              "owner_email": {
                                "description": "Its owner's address, which names it.",
                                "type": "string"
                              },
                              "role": {
                                "description": "The person's role in it.",
                                "enum": [
                                  "owner",
                                  "admin",
                                  "member"
                                ],
                                "type": "string"
                              }
                            },
                            "required": [
                              "object",
                              "account_id",
                              "owner_email",
                              "role",
                              "joined_at",
                              "deletes_at"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "activated_key_ids": {
                          "description": "IDs of the agent's pending live keys this call activated (agent_token); [] otherwise.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "credits_granted": {
                          "description": "Free credits this call granted (once per account); 0 otherwise.",
                          "type": "integer"
                        },
                        "deletion_canceled_at": {
                          "description": "When signing in last canceled this account's scheduled deletion (its API keys stayed revoked: create new ones), RFC 3339 UTC; null when it never was.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "email": {
                          "description": "The signed-in person's verified email address.",
                          "type": "string"
                        },
                        "expires_at": {
                          "description": "When the session ends, RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "free_credits_skipped": {
                          "description": "Why the account this session acts on has no free credits (Account.free_credits_skipped), for its owner; null otherwise.",
                          "enum": [
                            "disposable_address",
                            "domain_daily_limit",
                            "network_daily_limit",
                            "mailbox_used"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "fresh_until": {
                          "description": "Until when this session may create API keys and change keys without re-verifying (password or two-factor code), RFC 3339 UTC.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "new_api_keys": {
                          "description": "Keys this call created, with their secrets shown only here (a new account's first key, the first time its dashboard starts); [] otherwise.",
                          "items": {
                            "properties": {
                              "created_at": {
                                "description": "When the key was created, RFC 3339 UTC.",
                                "format": "date-time",
                                "type": "string"
                              },
                              "created_by_key": {
                                "description": "The API key (key_…) that last created this key, gave it the admin scope or rotated it: revoking that key also revokes this one if this one has admin. Null when none did, or a person has rotated it in the dashboard since.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "created_by_user": {
                                "description": "The person (GET /v1/members user_id) who created this key in the dashboard, or whose key created it. They may have left the account since. Null when no person did (an operator, or a key from before this was recorded).",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "dashboard": {
                                "description": "true for the account's built-in dashboard key: the dashboard's playground runs as it (so its requests are logged, counted and billed like any key's). Nobody holds its secret, so it works only from the signed-in dashboard. Only its spend_limit can be changed (to cap what the playground spends live); renaming, rescoping, restricting, rotating or revoking it is forbidden (details.reason dashboard_key). It is made on first use and revoked with the account.",
                                "type": "boolean"
                              },
                              "expires_at": {
                                "description": "When the key stops working, RFC 3339 UTC; null when it never expires.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "id": {
                                "description": "Key ID (key_…): manage the key with it. It is not the secret.",
                                "type": "string"
                              },
                              "ip_allowlist": {
                                "description": "IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; [] = any.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "last_used_at": {
                                "description": "About when the key was last used (updated at most hourly); null when never.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "name": {
                                "description": "Your label for the key.",
                                "type": "string"
                              },
                              "object": {
                                "description": "Always api_key.",
                                "enum": [
                                  "api_key"
                                ],
                                "type": "string"
                              },
                              "prefix": {
                                "description": "The secret's first characters, to recognize it.",
                                "type": "string"
                              },
                              "previous_secret_expires_at": {
                                "description": "Until then the secret this key had before its last rotation works too (rotate_secret), RFC 3339 UTC; null when none does.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "revoked_at": {
                                "description": "When the key was revoked; null while it is not.",
                                "format": "date-time",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "scopes": {
                                "description": "What the key may call: endpoints (data endpoints), jobs (create, read and cancel jobs; includes jobs:read), jobs:read (read jobs and their results), account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).",
                                "items": {
                                  "enum": [
                                    "endpoints",
                                    "jobs",
                                    "jobs:read",
                                    "account:read",
                                    "admin"
                                  ],
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "secret": {
                                "description": "The key itself: send it in the x-api-key header. Shown only once: store it now.",
                                "type": "string"
                              },
                              "spend_limit": {
                                "description": "The key's spend limit and what it used this interval; null when the key has none.",
                                "properties": {
                                  "amount": {
                                    "description": "Most credits the key may spend per interval.",
                                    "type": "integer"
                                  },
                                  "interval": {
                                    "description": "Calendar day or month, UTC.",
                                    "enum": [
                                      "day",
                                      "month"
                                    ],
                                    "type": "string"
                                  },
                                  "resets_at": {
                                    "description": "Start of the next interval, RFC 3339 UTC.",
                                    "format": "date-time",
                                    "type": "string"
                                  },
                                  "used": {
                                    "description": "Credits the key spent this interval, plus what its requests in flight hold.",
                                    "type": "integer"
                                  }
                                },
                                "required": [
                                  "amount",
                                  "interval",
                                  "used",
                                  "resets_at"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              },
                              "status": {
                                "description": "pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.",
                                "enum": [
                                  "active",
                                  "pending",
                                  "expired",
                                  "revoked"
                                ],
                                "type": "string"
                              }
                            },
                            "required": [
                              "object",
                              "id",
                              "name",
                              "status",
                              "prefix",
                              "scopes",
                              "spend_limit",
                              "expires_at",
                              "ip_allowlist",
                              "created_at",
                              "last_used_at",
                              "revoked_at",
                              "dashboard",
                              "previous_secret_expires_at",
                              "created_by_key",
                              "created_by_user",
                              "secret"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "object": {
                          "description": "Always session.",
                          "enum": [
                            "session"
                          ],
                          "type": "string"
                        },
                        "role": {
                          "description": "The signed-in person's role in this account (account_id): what the dashboard lets them do here.",
                          "enum": [
                            "owner",
                            "admin",
                            "member"
                          ],
                          "type": "string"
                        },
                        "setup_required": {
                          "description": "Whether POST /v1/session still has this account's setting up to do: a new account's first key (its secret in its answer, once), or the decision on an agent-made account. False in POST /v1/session's own answer once it has done it.",
                          "type": "boolean"
                        },
                        "two_factor_enabled": {
                          "description": "Whether the signed-in person has two-factor authentication on.",
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "object",
                        "account_id",
                        "email",
                        "expires_at",
                        "new_api_keys",
                        "activated_key_ids",
                        "credits_granted",
                        "free_credits_skipped",
                        "two_factor_enabled",
                        "fresh_until",
                        "role",
                        "accounts",
                        "deletion_canceled_at",
                        "setup_required"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Start the dashboard: set up the account",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Start the dashboard: set up the account",
        "tags": [
          "Signup"
        ],
        "x-socialtap-auth": {
          "auth": "session",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/snapchat/comments": {
      "get": {
        "description": "Returns the comments on a public Snapchat Spotlight, or one comment's replies, from the Spotlight's link or ID. Each comment has its text, posting time, exact like and reply counts, whether the Spotlight's poster wrote or favorited it, and the commenter's ID, name, picture, verified badge, and username where Snapchat shows one. Comments come a page at a time, in Snapchat's own ranking.\n\nReturns `{data, page, meta}`: `data` holds up to 26 `Comment` items (the shared schema, the same on every platform), Snapchat's own ranking of the Spotlight's comments; a comment's replies oldest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/snapchat/comments/ (Markdown: https://socialtap.dev/docs/reference/snapchat/comments/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/snapchat/comments/index.md)",
          "url": "https://socialtap.dev/docs/reference/snapchat/comments/"
        },
        "operationId": "snapchat.comments.list",
        "parameters": [
          {
            "description": "The Spotlight: its link (https://www.snapchat.com/@mrbeast/spotlight/<id>, /spotlight/<id>, /add/<name>/spotlight/<id>, /p/<publisher>/spotlight/<id>, /web/spotlight/<id>, with or without /embed, or a share link) or its bare ID.",
            "example": "https://www.snapchat.com/@mrbeast/spotlight/W7_EDlXWTBiXAEEniNoMPwAAYbHZzZmtrYm1jAZhMOQmTAZhMOQfqAAAAAQ",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The Spotlight: its link (https://www.snapchat.com/@mrbeast/spotlight/<id>, /spotlight/<id>, /add/<name>/spotlight/<id>, /p/<publisher>/spotlight/<id>, /web/spotlight/<id>, with or without /embed, or a share link) or its bare ID.",
              "examples": [
                "https://www.snapchat.com/@mrbeast/spotlight/W7_EDlXWTBiXAEEniNoMPwAAYbHZzZmtrYm1jAZhMOQmTAZhMOQfqAAAAAQ"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "List this comment's replies instead of the Spotlight's comments: the id of a comment from this endpoint.",
            "example": "a592688a-c0e3-4544-9441-665cbcc684ac",
            "in": "query",
            "name": "comment_id",
            "schema": {
              "description": "List this comment's replies instead of the Spotlight's comments: the id of a comment from this endpoint.",
              "examples": [
                "a592688a-c0e3-4544-9441-665cbcc684ac"
              ],
              "maxLength": 36,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 26,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 26,
              "maximum": 26,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://cf-st.sc-cdn.net/3d/render/38357514-103501769400_23-s5-v1.webp?ua=2",
                            "display_name": "Sadeeq™️",
                            "id": "5c3014ea-7aef-433d-be14-617eef3666bb",
                            "is_verified": false,
                            "url": null,
                            "username": null
                          },
                          "edited_at": null,
                          "id": "a592688a-c0e3-4544-9441-665cbcc684ac",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": false,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 1592,
                            "reply_count": 13
                          },
                          "parent_id": null,
                          "platform": "snapchat",
                          "platform_specific": {
                            "snapchat": {
                              "author_user_id": "5c3014ea-7aef-433d-be14-617eef3666bb"
                            }
                          },
                          "post_id": "W7_EDlXWTBiXAEEniNoMPwAAYbHZzZmtrYm1jAZhMOQmTAZhMOQfqAAAAAQ",
                          "published_at": "2025-07-27T14:25:17Z",
                          "text": "You cheater 😭",
                          "unknown_fields": [],
                          "url": null
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://cf-st.sc-cdn.net/3d/render/31151407-103950905393_19-s5-v1.webp?ua=2",
                            "display_name": "Lucy",
                            "id": "838f5544-0aa2-40b5-9911-d310032b3d87",
                            "is_verified": false,
                            "url": null,
                            "username": null
                          },
                          "edited_at": null,
                          "id": "a7c58936-d969-4205-b114-aa8ba9cc841c",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": false,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 1299,
                            "reply_count": 72
                          },
                          "parent_id": null,
                          "platform": "snapchat",
                          "platform_specific": {
                            "snapchat": {
                              "author_user_id": "838f5544-0aa2-40b5-9911-d310032b3d87"
                            }
                          },
                          "post_id": "W7_EDlXWTBiXAEEniNoMPwAAYbHZzZmtrYm1jAZhMOQmTAZhMOQfqAAAAAQ",
                          "published_at": "2025-09-14T15:23:53Z",
                          "text": "Mr beast haters-------------------------->",
                          "unknown_fields": [],
                          "url": null
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://cf-st.sc-cdn.net/aps/bolt/aHR0cHM6Ly9jZi1zdC5zYy1jZG4ubmV0L2QvdnNRVVdPN3dJTTJETHF5T3ZzSE1KP2JvPUVna3lBUVJJQWxBWllBRSUzRCZ1Yz0yNQ._RS0,640_FMjpeg",
                            "display_name": "𝐊𝐚𝐭𝐞𝐫𝐢𝐧𝐚💋ྀི",
                            "id": "e6252914-86c7-4aef-86fe-e53f0dd89218",
                            "is_verified": false,
                            "url": null,
                            "username": null
                          },
                          "edited_at": null,
                          "id": "00c351f3-6d8d-43fa-ab44-0ffbb6b5b210",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": false,
                          "is_pinned": null,
                          "metrics": {
                            "like_count": 1385,
                            "reply_count": 9
                          },
                          "parent_id": null,
                          "platform": "snapchat",
                          "platform_specific": {
                            "snapchat": {
                              "author_user_id": "a53d0b5d-5c95-4a79-bb04-02931574f0be"
                            }
                          },
                          "post_id": "W7_EDlXWTBiXAEEniNoMPwAAYbHZzZmtrYm1jAZhMOQmTAZhMOQfqAAAAAQ",
                          "published_at": "2025-08-04T17:06:39Z",
                          "text": "Bro this is cheating",
                          "unknown_fields": [],
                          "url": null
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "snapchat",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 343,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "W7_EDlXWTBiXAEEniNoMPwAAYbHZzZmtrYm1jAZhMOQmTAZhMOQfqAAAAAQ",
                          "url": "https://www.snapchat.com/spotlight/W7_EDlXWTBiXAEEniNoMPwAAYbHZzZmtrYm1jAZhMOQmTAZhMOQfqAAAAAQ"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SnapchatCommentsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Spotlight comments and replies with like counts",
        "tags": [
          "Snapchat"
        ],
        "x-socialtap-endpoint": "snapchat.comments",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Snapchat's own ranking of the Spotlight's comments; a comment's replies oldest first",
          "page_max": 26,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/snapchat/profile": {
      "get": {
        "description": "Returns a public Snapchat profile from its username or link, with its subscriber count, bio, links, public Story and the Spotlights its page shows. It also has the name, picture, banner, verified star, category, the place it names, its Snapcode, when the public profile was created and last changed, the Stories it saved with each Snap's file, and the accounts its page recommends.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\nIn Snapchat's words: `metrics.follower_count` is subscribers.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/snapchat/profile/ (Markdown: https://socialtap.dev/docs/reference/snapchat/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/snapchat/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/snapchat/profile/"
        },
        "operationId": "snapchat.profile.get",
        "parameters": [
          {
            "description": "The account: its username (mrbeast, with or without the @) or its link (https://www.snapchat.com/@mrbeast, https://www.snapchat.com/add/mrbeast, or a saved Story's link on its page).",
            "example": "nasa",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The account: its username (mrbeast, with or without the @) or its link (https://www.snapchat.com/@mrbeast, https://www.snapchat.com/add/mrbeast, or a saved Story's link on its page).",
              "examples": [
                "mrbeast"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "metrics.follower_count"
                        ],
                        "avatar_url": "https://cf-st.sc-cdn.net/aps/bolt/aHR0cHM6Ly9jZi1zdC5zYy1jZG4ubmV0L2QvUVg2VHZkaDBHNUMzcXVidWhWaTJhP2JvPUVnMGFBQm9BTWdFRVNBSlFHV0FCJnVjPTI1._RS0,90_FMjpeg",
                        "banner_url": "https://cf-st.sc-cdn.net/aps/bolt/aHR0cHM6Ly9jZi1zdC5zYy1jZG4ubmV0L2QvalRSaVBkS2NYWmJlV0w4dXNPeWNtP2JvPUVna3lBUVJJQWxBWllBRSUzRCZ1Yz0yNQ._RS0,1080_FMjpeg",
                        "bio": "Explore the universe and discover our home planet with official NASA snaps.",
                        "category": "Government Org",
                        "country_code": null,
                        "created_at": "2019-05-22T17:38:27Z",
                        "display_name": "NASA",
                        "external_links": [
                          {
                            "title": null,
                            "url": "https://www.nasa.gov"
                          }
                        ],
                        "id": "cb983b26-c537-474b-9699-065309205ea2",
                        "is_private": false,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 751900,
                          "following_count": null,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "snapchat",
                        "platform_specific": {
                          "snapchat": {
                            "category_id": "public-profile-category-v3-business-group",
                            "highlights": [
                              {
                                "id": "ddf02468-ae16-4fc6-b1bc-bde7e1e22218",
                                "snaps": [
                                  {
                                    "id": null,
                                    "media_url": "https://cf-st.sc-cdn.net/d/wAUDrJs74QBAl504N3DhT.1322?mo=GlcaFDIBBDoBfUIGCMWw5M4GSAJQXmABUMIBWgdEZk1lZGlhogEuCKoKEiUKIwiFuBsgATDgAzjUBkABSg4KCRwFBwgHBwkJBxD0A1CQTmgCIgISAJADkE4%3D&uc=94",
                                    "posted_at": "2026-04-10T15:32:54Z",
                                    "preview_url": "https://cf-st.sc-cdn.net/d/wAUDrJs74QBAl504N3DhT.410?mo=GjUaFDIBBDoBfUIGCMWw5M4GSAJQXmABUMUBWhBEZkxhcmdlVGh1bWJuYWlsogEHCJoDIgISAA%3D%3D&uc=94",
                                    "type": "video"
                                  },
                                  {
                                    "id": null,
                                    "media_url": "https://cf-st.sc-cdn.net/d/h2ao1JvA4lER8PICU97Gc.1322?mo=GlcaFDIBBDoBfUIGCMaw5M4GSAJQXmABUMIBWgdEZk1lZGlhogEuCKoKEiUKIwiZ_h4gATDgAzjUBkABSg4KCWUqPz0-DQ0LERD0A1CQTmgCIgISAJADkE4%3D&uc=94",
                                    "posted_at": "2026-04-10T15:32:54Z",
                                    "preview_url": "https://cf-st.sc-cdn.net/d/h2ao1JvA4lER8PICU97Gc.410?mo=GjUaFDIBBDoBfUIGCMaw5M4GSAJQXmABUMUBWhBEZkxhcmdlVGh1bWJuYWlsogEHCJoDIgISAA%3D%3D&uc=94",
                                    "type": "video"
                                  },
                                  {
                                    "id": null,
                                    "media_url": "https://cf-st.sc-cdn.net/d/YDbAuRYXd4SZKC9GSLTOa.1322?mo=GlcaFDIBBDoBfUIGCMew5M4GSAJQXmABUMIBWgdEZk1lZGlhogEuCKoKEiUKIwifrxAgATDgAzjUBkABSg4KCR4KCwwMCAg2ChD0A1CQTmgCIgISAJADkE4%3D&uc=94",
                                    "posted_at": "2026-04-10T15:32:54Z",
                                    "preview_url": "https://cf-st.sc-cdn.net/d/YDbAuRYXd4SZKC9GSLTOa.410?mo=GjUaFDIBBDoBfUIGCMew5M4GSAJQXmABUMUBWhBEZkxhcmdlVGh1bWJuYWlsogEHCJoDIgISAA%3D%3D&uc=94",
                                    "type": "video"
                                  }
                                ],
                                "thumbnail_url": "https://cf-st.sc-cdn.net/d/wAUDrJs74QBAl504N3DhT.410?mo=GjUaFDIBBDoBfUIGCMWw5M4GSAJQXmABUMUBWhBEZkxhcmdlVGh1bWJuYWlsogEHCJoDIgISAA%3D%3D&uc=94",
                                "title": "Moon Joy",
                                "url": "https://www.snapchat.com/@nasa/highlight/ddf02468-ae16-4fc6-b1bc-bde7e1e22218"
                              },
                              {
                                "id": "7479819b-d2de-44ff-a394-8db45a27c8d6",
                                "snaps": [
                                  {
                                    "id": null,
                                    "media_url": "https://cf-st.sc-cdn.net/d/C7eHkq29ayMBY0xtSF9ej.1322.IRZXSOY?mo=GmMaFDIBBDoBfUIGCJX73s4GSAJQXmABUMIBWgdEZk1lZGlhogE5CKoKEicKJQiHstsBIAEw4AM41AZAAUoOCglwHCAdHTApMCAQ9ANQ-vMCaAIiCxIAKgdJUlpYU09ZkAP68wI%3D&uc=94",
                                    "posted_at": "2026-04-05T21:51:39Z",
                                    "preview_url": "https://cf-st.sc-cdn.net/d/C7eHkq29ayMBY0xtSF9ej.410.IRZXSOY?mo=Gj4aFDIBBDoBfUIGCJT73s4GSAJQXmABUMUBWhBEZkxhcmdlVGh1bWJuYWlsogEQCJoDIgsSACoHSVJaWFNPWQ%3D%3D&uc=94",
                                    "type": "video"
                                  }
                                ],
                                "thumbnail_url": "https://cf-st.sc-cdn.net/d/C7eHkq29ayMBY0xtSF9ej.410.IRZXSOY?mo=Gj4aFDIBBDoBfUIGCJT73s4GSAJQXmABUMUBWhBEZkxhcmdlVGh1bWJuYWlsogEQCJoDIgsSACoHSVJaWFNPWQ%3D%3D&uc=94",
                                "title": "Full Capsule",
                                "url": "https://www.snapchat.com/@nasa/highlight/7479819b-d2de-44ff-a394-8db45a27c8d6"
                              },
                              {
                                "id": "c19cac68-98fd-41b4-86bf-7fa92bf811e5",
                                "snaps": [
                                  {
                                    "id": null,
                                    "media_url": "https://cf-st.sc-cdn.net/d/5urEaYR1imCPiQdHtyuAs.1322.IRZXSOY?mo=GmIaFDIBBDoBfUIGCNb53s4GSAJQXmABUMIBWgdEZk1lZGlhogE4CKoKEiYKJAjounggATDgAzjUBkABSg4KCT8zEA9WQjcsFhD0A1DK_AFoAiILEgAqB0lSWlhTT1mQA8r8AQ%3D%3D&uc=94",
                                    "posted_at": "2026-04-04T18:53:30Z",
                                    "preview_url": "https://cf-st.sc-cdn.net/d/5urEaYR1imCPiQdHtyuAs.410.IRZXSOY?mo=Gj4aFDIBBDoBfUIGCNb53s4GSAJQXmABUMUBWhBEZkxhcmdlVGh1bWJuYWlsogEQCJoDIgsSACoHSVJaWFNPWQ%3D%3D&uc=94",
                                    "type": "video"
                                  }
                                ],
                                "thumbnail_url": "https://cf-st.sc-cdn.net/d/5urEaYR1imCPiQdHtyuAs.410.IRZXSOY?mo=Gj4aFDIBBDoBfUIGCNb53s4GSAJQXmABUMUBWhBEZkxhcmdlVGh1bWJuYWlsogEQCJoDIgsSACoHSVJaWFNPWQ%3D%3D&uc=94",
                                "title": "Launch of Artemis II",
                                "url": "https://www.snapchat.com/@nasa/highlight/c19cac68-98fd-41b4-86bf-7fa92bf811e5"
                              }
                            ],
                            "is_highlights_shown": true,
                            "is_spotlights_public": true,
                            "is_story_live": false,
                            "last_updated_at": "2026-10-12T16:36:39Z",
                            "related_accounts": [
                              {
                                "avatar_url": "https://cf-st.sc-cdn.net/aps/bolt/aHR0cHM6Ly9jZi1zdC5zYy1jZG4ubmV0L2QvWW1tSUZkY2JlZTNrZVl5bVlQbEpxP2JvPUVnMGFBQm9BTWdFRVNBSlFDR0FCJnVjPTg._RS0,640_FMpng",
                                "display_name": "Destin Smarter Every Day",
                                "id": "a0f96d01-d4c8-4172-b8bf-50f592e6f49f",
                                "is_verified": false,
                                "url": "https://www.snapchat.com/@ilikerockets",
                                "username": "ilikerockets"
                              },
                              {
                                "avatar_url": "https://cf-st.sc-cdn.net/aps/bolt/aHR0cHM6Ly9jZi1zdC5zYy1jZG4ubmV0L2QvWW1tSUZkY2JlZTNrZVl5bVlQbEpxP2JvPUVnMGFBQm9BTWdFRVNBSlFDR0FCJnVjPTg._RS0,640_FMpng",
                                "display_name": "The White House",
                                "id": "9e2952fe-4a97-43d5-b20a-5a2fa2e2a1cd",
                                "is_verified": true,
                                "url": "https://www.snapchat.com/@whitehouse",
                                "username": "whitehouse"
                              },
                              {
                                "avatar_url": "https://cf-st.sc-cdn.net/aps/bolt/aHR0cHM6Ly9jZi1zdC5zYy1jZG4ubmV0L2QvWW1tSUZkY2JlZTNrZVl5bVlQbEpxP2JvPUVnMGFBQm9BTWdFRVNBSlFDR0FCJnVjPTg._RS0,640_FMpng",
                                "display_name": "Hank",
                                "id": "d09c44d1-86fe-4c52-9efc-c23c3213711c",
                                "is_verified": false,
                                "url": "https://www.snapchat.com/@hankgre",
                                "username": "hankgre"
                              }
                            ],
                            "snapcode_url": "https://app.snapchat.com/web/deeplink/snapcode?username=nasa&type=SVG&bitmoji=enable",
                            "spotlights": [
                              {
                                "caption": null,
                                "duration_ms": 87330,
                                "height": 960,
                                "id": "W7_EDlXWTBiXAEEniNoMPwAAYeG9xcGd0ZWd3AZ14BVv0AZ14BQkrAAAAAQ",
                                "media_url": "https://cf-st.sc-cdn.net/d/1z1p5kZtkBheBrRMCmyGi.27.IRZXSOY?mo=GmAaCTIBBEgCUC5gAVCiAVoQU3BvdGxpZ2h0U2hhcmluZ6IBOAgbEicKJQitz60DIAEwnAQ4wAdAAUoOCgl_EBAQEBEREw8Q9ANQoqoFaAIiCxIAKgdJUlpYU09ZkAOiqgU%3D&uc=46",
                                "metrics": {
                                  "comment_count": 138,
                                  "like_count": 2356,
                                  "recommend_count": 120,
                                  "share_count": 165,
                                  "view_count": 25162
                                },
                                "published_at": "2026-04-10T15:31:29Z",
                                "thumbnail_url": "https://cf-st.sc-cdn.net/d/1z1p5kZtkBheBrRMCmyGi.256.IRZXSOY?mo=GkYaCTIBBEgCUC5gAVCgAVoQRGZMYXJnZVRodW1ibmFpbKIBEAiAAiILEgAqB0lSWlhTT1miARAImgoiCxIAKgdJUlpYU09Z&uc=46",
                                "type": "video",
                                "url": "https://www.snapchat.com/@nasa/spotlight/W7_EDlXWTBiXAEEniNoMPwAAYeG9xcGd0ZWd3AZ14BVv0AZ14BQkrAAAAAQ",
                                "width": 540
                              },
                              {
                                "caption": null,
                                "duration_ms": 74870,
                                "height": 960,
                                "id": "W7_EDlXWTBiXAEEniNoMPwAAYdHBmbG9hdHR0AZ1ytS-RAZ1ytSiwAAAAAQ",
                                "media_url": "https://cf-st.sc-cdn.net/d/jspypYdgsWceo4YzSltMj.27.IRZXSOY?mo=GmEaCTIBBEgCUC5gAVCiAVoQU3BvdGxpZ2h0U2hhcmluZ6IBOQgbEigKJgjvza0DIAEwnAQ4wAdAAUoPCgqxASojIhodIRoaEPQDUPbIBGgCIgsSACoHSVJaWFNPWZAD9sgE&uc=46",
                                "metrics": {
                                  "comment_count": 104,
                                  "like_count": 1584,
                                  "recommend_count": 85,
                                  "share_count": 55,
                                  "view_count": 25910
                                },
                                "published_at": "2026-04-09T14:46:08Z",
                                "thumbnail_url": "https://cf-st.sc-cdn.net/d/jspypYdgsWceo4YzSltMj.256.IRZXSOY?mo=GkYaCTIBBEgCUC5gAVCgAVoQRGZMYXJnZVRodW1ibmFpbKIBEAiAAiILEgAqB0lSWlhTT1miARAImgoiCxIAKgdJUlpYU09Z&uc=46",
                                "type": "video",
                                "url": "https://www.snapchat.com/@nasa/spotlight/W7_EDlXWTBiXAEEniNoMPwAAYdHBmbG9hdHR0AZ1ytS-RAZ1ytSiwAAAAAQ",
                                "width": 540
                              },
                              {
                                "caption": null,
                                "duration_ms": 47610,
                                "height": 960,
                                "id": "W7_EDlXWTBiXAEEniNoMPwAAYbHlkdWd2eXNnAZ1foYTBAZ1foUxRAAAAAQ",
                                "media_url": "https://cf-st.sc-cdn.net/d/C7eHkq29ayMBY0xtSF9ej.27.IRZXSOY?mo=GmEaCTIBBEgCUC5gAVCiAVoQU3BvdGxpZ2h0U2hhcmluZ6IBOQgbEigKJgjAtMACIAEwnAQ4wAdAAUoPCgqYATIuJS1IPUQvEPQDUPrzAmgCIgsSACoHSVJaWFNPWZAD-vMC&uc=46",
                                "metrics": {
                                  "comment_count": 241,
                                  "like_count": 6567,
                                  "recommend_count": 313,
                                  "share_count": 467,
                                  "view_count": 69478
                                },
                                "published_at": "2026-04-05T21:51:39Z",
                                "thumbnail_url": "https://cf-st.sc-cdn.net/d/C7eHkq29ayMBY0xtSF9ej.256.IRZXSOY?mo=GkYaCTIBBEgCUC5gAVCgAVoQRGZMYXJnZVRodW1ibmFpbKIBEAiAAiILEgAqB0lSWlhTT1miARAImgoiCxIAKgdJUlpYU09Z&uc=46",
                                "type": "video",
                                "url": "https://www.snapchat.com/@nasa/spotlight/W7_EDlXWTBiXAEEniNoMPwAAYbHlkdWd2eXNnAZ1foYTBAZ1foUxRAAAAAQ",
                                "width": 540
                              }
                            ],
                            "story": null,
                            "subcategory_id": "public-profile-subcategory-v3-government-org",
                            "user_id": "92ea5bae-4f78-4611-ba8c-a60235ac2b49"
                          }
                        },
                        "type": "organization",
                        "unknown_fields": [],
                        "url": "https://www.snapchat.com/@nasa",
                        "username": "nasa"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "snapchat",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 279,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "cb983b26-c537-474b-9699-065309205ea2",
                          "url": "https://www.snapchat.com/@nasa"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SnapchatProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Subscribers, bio, Story and Spotlights",
        "tags": [
          "Snapchat"
        ],
        "x-socialtap-endpoint": "snapchat.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/snapchat/spotlight": {
      "get": {
        "description": "Returns a public Snapchat Spotlight from its link or ID, with its video file, exact views and likes, and Snapchat's timed transcript. It also has the caption and the text written on the Snap, the posting time, the poster, exact comment, share and recommend counts, hashtags and mentions, the sound, Lens and place it credits, and the title, description and keywords Snapchat generated for it.\n\nReturns `{data, meta}`: `data` is a `Post` object (Snapchat calls it a spotlight) (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/snapchat/spotlight/ (Markdown: https://socialtap.dev/docs/reference/snapchat/spotlight/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/snapchat/spotlight/index.md)",
          "url": "https://socialtap.dev/docs/reference/snapchat/spotlight/"
        },
        "operationId": "snapchat.spotlight.get",
        "parameters": [
          {
            "description": "The Spotlight: its link (https://www.snapchat.com/@mrbeast/spotlight/<id>, /spotlight/<id>, either with /embed, /add/<username>/spotlight/<id>, or a share link) or its bare ID.",
            "example": "https://www.snapchat.com/@mrbeast/spotlight/W7_EDlXWTBiXAEEniNoMPwAAYbHZzZmtrYm1jAZhMOQmTAZhMOQfqAAAAAQ",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The Spotlight: its link (https://www.snapchat.com/@mrbeast/spotlight/<id>, /spotlight/<id>, either with /embed, /add/<username>/spotlight/<id>, or a share link) or its bare ID.",
              "examples": [
                "https://www.snapchat.com/@mrbeast/spotlight/W7_EDlXWTBiXAEEniNoMPwAAYbHZzZmtrYm1jAZhMOQmTAZhMOQfqAAAAAQ"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://cf-st.sc-cdn.net/aps/bolt/aHR0cHM6Ly9jZi1zdC5zYy1jZG4ubmV0L2QvR2M2MEJNODVEdjRHWU5yVk9EbFZwP2JvPUVnMGFBQm9BTWdFRVNBSlFHV0FCJnVjPTI1._RS0,640_FMpng",
                          "display_name": "MrBeast",
                          "id": "fe63dec1-4fa4-476c-9c73-19b2bc2e8589",
                          "is_verified": true,
                          "url": "https://www.snapchat.com/@mrbeast",
                          "username": "mrbeast"
                        },
                        "coauthors": [],
                        "duration_ms": 34530,
                        "hashtags": [],
                        "id": "W7_EDlXWTBiXAEEniNoMPwAAYbHZzZmtrYm1jAZhMOQmTAZhMOQfqAAAAAQ",
                        "is_nsfw": null,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": null,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": 34530,
                            "expires_at": null,
                            "height": 960,
                            "thumbnail_url": "https://cf-st.sc-cdn.net/d/d6nFuppwNzMxcK3GIikG4.256.IRZXSOY?mo=GkkaBzIBBFAuYAFaEERmTGFyZ2VUaHVtYm5haWyiARQIgAIiDwoCSAQSACoHSVJaWFNPWaIBFAiaCiIPCgJIAhIAKgdJUlpYU09Z&uc=46",
                            "type": "video",
                            "url": "https://cf-st.sc-cdn.net/d/d6nFuppwNzMxcK3GIikG4.27.IRZXSOY?mo=Gl4aCTIBBEgDUC5gAVoQU3BvdGxpZ2h0U2hhcmluZ6IBOQgbEigKJgjUpb0CIAEwnAQ4wAdAAUoPCgqWAUNIOVQ6WUBnEPQDUOKNAmgCIgsSACoHSVJaWFNPWZAD4o0C&uc=46",
                            "width": 540
                          }
                        ],
                        "mentions": [],
                        "metrics": {
                          "comment_count": 2278,
                          "like_count": 65723,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": null,
                          "share_count": 882,
                          "view_count": 3843573
                        },
                        "platform": "snapchat",
                        "platform_specific": {
                          "snapchat": {
                            "embedded_text": null,
                            "generated_description": "In this thrilling challenge hosted by MrBeast, two teams—one in blue, one in red—race to climb a massive staircase. One side is coated in a slippery yellow substance, while the other is covered in white powder, making every step a test of balance and teamwork. The competition is …",
                            "generated_title": "MrBeast's Epic Staircase Challenge: Slippery Climb & Prize Win!",
                            "is_attributed": true,
                            "keywords": [
                              "standup comedy",
                              "teamwork",
                              "impressions"
                            ],
                            "lens": null,
                            "place": null,
                            "recommend_count": 4718,
                            "sound": {
                              "id": "108313924108",
                              "subtitle": "mrbeast",
                              "thumbnail_url": "https://cf-st.sc-cdn.net/d/6YKRUxipwtyh6YMgtaJbK?bo=Eg0aABoAMgEESAJQCGAB&uc=8",
                              "title": "Original Sound"
                            },
                            "transcript": null,
                            "transcript_url": "https://bolt-gcdn.sc-cdn.net/3/bgssITIneW2swg0tH6SC2.vtt?bo=EgkyAX1IAlAuYAE%3D&uc=46"
                          }
                        },
                        "platform_type": "spotlight",
                        "published_at": "2025-07-27T14:11:02Z",
                        "text": "Slippery vs Sticky Stairs",
                        "thumbnail_url": "https://cf-st.sc-cdn.net/d/d6nFuppwNzMxcK3GIikG4.256.IRZXSOY?mo=GkkaBzIBBFAuYAFaEERmTGFyZ2VUaHVtYm5haWyiARQIgAIiDwoCSAQSACoHSVJaWFNPWaIBFAiaCiIPCgJIAhIAKgdJUlpYU09Z&uc=46",
                        "title": null,
                        "type": "video",
                        "unknown_fields": [],
                        "url": "https://www.snapchat.com/@mrbeast/spotlight/W7_EDlXWTBiXAEEniNoMPwAAYbHZzZmtrYm1jAZhMOQmTAZhMOQfqAAAAAQ"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "snapchat",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 7127,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "W7_EDlXWTBiXAEEniNoMPwAAYbHZzZmtrYm1jAZhMOQmTAZhMOQfqAAAAAQ",
                          "url": "https://www.snapchat.com/@mrbeast/spotlight/W7_EDlXWTBiXAEEniNoMPwAAYbHZzZmtrYm1jAZhMOQmTAZhMOQfqAAAAAQ"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SnapchatSpotlightResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Video or image with exact views and likes",
        "tags": [
          "Snapchat"
        ],
        "x-socialtap-endpoint": "snapchat.spotlight",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/soundcloud/artist": {
      "get": {
        "description": "Returns a public SoundCloud artist from its name, link, URN or ID, with exact follower and following counts, bio and the links it lists. It also has the picture and banner, verified badge, city and country, track and playlist counts, likes given, Pro badge and creator plan, and when the profile last changed. Each link names its service, and some accounts list an email among them.\n\nReturns `{data, meta}`: `data` is a `Profile` object (SoundCloud calls it a artist) (the shared schema, the same on every platform). Null means unknown.\n\nIn SoundCloud's words: `metrics.post_count` is tracks SoundCloud states (not its list).\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/soundcloud/artist/ (Markdown: https://socialtap.dev/docs/reference/soundcloud/artist/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/soundcloud/artist/index.md)",
          "url": "https://socialtap.dev/docs/reference/soundcloud/artist/"
        },
        "operationId": "soundcloud.artist.get",
        "parameters": [
          {
            "description": "The account: its name in links (forss, with or without the @; @123 is an account named 123), its link (soundcloud.com/forss, also on m.soundcloud.com, any tab of it such as /tracks or /likes, with any share parameters), its address on the API (api.soundcloud.com/users/183), its URN (soundcloud:users:183) or its numeric ID (183). Names are case-insensitive. A share link (on.soundcloud.com/<code>) is not read here: pass what it leads to.",
            "example": "forss",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The account: its name in links (forss, with or without the @; @123 is an account named 123), its link (soundcloud.com/forss, also on m.soundcloud.com, any tab of it such as /tracks or /likes, with any share parameters), its address on the API (api.soundcloud.com/users/183), its URN (soundcloud:users:183) or its numeric ID (183). Names are case-insensitive. A share link (on.soundcloud.com/<code>) is not read here: pass what it leads to.",
              "examples": [
                "forss"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://i1.sndcdn.com/avatars-000012778523-59quu3-t1080x1080.jpg",
                        "banner_url": "https://i1.sndcdn.com/visuals-000000000183-juJMfF-original.jpg",
                        "bio": "Artist & Founder SoundCloud",
                        "category": null,
                        "country_code": null,
                        "created_at": null,
                        "display_name": "Forss",
                        "external_links": [
                          {
                            "title": "Forss Official Site",
                            "url": "http://forssmusic.com/"
                          },
                          {
                            "title": "facebook",
                            "url": "http://facebook.com/forssmusic"
                          },
                          {
                            "title": "twitter",
                            "url": "http://twitter.com/Forssmusic"
                          }
                        ],
                        "id": "183",
                        "is_private": null,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 132108,
                          "following_count": 1254,
                          "post_count": 26,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "soundcloud",
                        "platform_specific": {
                          "soundcloud": {
                            "first_name": "Eric",
                            "full_name": "Eric Quidenus-Wahlforss",
                            "is_creator_mid_tier": false,
                            "is_pro": false,
                            "is_pro_unlimited": true,
                            "last_modified_at": "2023-03-28T16:19:18Z",
                            "last_name": "Quidenus-Wahlforss",
                            "liked_playlist_count": 10,
                            "liked_track_count": 288,
                            "plan": "creator-pro-unlimited",
                            "playlist_count": 4,
                            "repost_count": null,
                            "social_links": [
                              {
                                "network": "personal",
                                "title": "Forss Official Site",
                                "url": "http://forssmusic.com/",
                                "username": null
                              },
                              {
                                "network": "facebook",
                                "title": null,
                                "url": "http://facebook.com/forssmusic",
                                "username": "forssmusic"
                              },
                              {
                                "network": "twitter",
                                "title": null,
                                "url": "http://twitter.com/Forssmusic",
                                "username": "Forssmusic"
                              }
                            ]
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://soundcloud.com/forss",
                        "username": "forss"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "soundcloud",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 424,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "183",
                          "url": "https://soundcloud.com/forss"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SoundcloudArtistResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact followers, bio and social links",
        "tags": [
          "SoundCloud"
        ],
        "x-socialtap-endpoint": "soundcloud.artist",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/soundcloud/track": {
      "get": {
        "description": "Returns a public SoundCloud track from its link, share link, URN or ID, with exact play, like, repost, comment and download counts. It also has the title, description, hashtags, artwork, length, release and upload dates, uploader, genre, tags, license, and the album, ISRC, UPC, label, publisher and copyright that labels fill in. It says whether the track plays in full or as a preview in the United States.\n\nReturns `{data, meta}`: `data` is a `Post` object (SoundCloud calls it a track) (the shared schema, the same on every platform). Null means unknown.\n\nIn SoundCloud's words: `metrics.view_count` is plays.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/soundcloud/track/ (Markdown: https://socialtap.dev/docs/reference/soundcloud/track/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/soundcloud/track/index.md)",
          "url": "https://socialtap.dev/docs/reference/soundcloud/track/"
        },
        "operationId": "soundcloud.track.get",
        "parameters": [
          {
            "description": "The track: its link (soundcloud.com/forss/flickermood, also on m.soundcloud.com, with any share parameters), a share link (on.soundcloud.com/<code>), its address on the API (api.soundcloud.com/tracks/293), the embedded player's link to it, its URN (soundcloud:tracks:293) or its ID (293).",
            "example": "https://soundcloud.com/forss/flickermood",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The track: its link (soundcloud.com/forss/flickermood, also on m.soundcloud.com, with any share parameters), a share link (on.soundcloud.com/<code>), its address on the API (api.soundcloud.com/tracks/293), the embedded player's link to it, its URN (soundcloud:tracks:293) or its ID (293).",
              "examples": [
                "https://soundcloud.com/forss/flickermood"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://i1.sndcdn.com/avatars-000012778523-59quu3-t500x500.jpg",
                          "display_name": "Forss",
                          "id": "183",
                          "is_verified": true,
                          "url": "https://soundcloud.com/forss",
                          "username": "forss"
                        },
                        "coauthors": [],
                        "duration_ms": 213890,
                        "hashtags": [],
                        "id": "293",
                        "is_nsfw": null,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": null,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": 213886,
                            "expires_at": null,
                            "height": null,
                            "thumbnail_url": "https://i1.sndcdn.com/artworks-000067273316-smsiqx-t500x500.jpg",
                            "type": "audio",
                            "url": null,
                            "width": null
                          }
                        ],
                        "mentions": [],
                        "metrics": {
                          "comment_count": 400,
                          "like_count": 2621,
                          "quote_count": null,
                          "repost_count": 413,
                          "save_count": null,
                          "share_count": null,
                          "view_count": 972697
                        },
                        "platform": "soundcloud",
                        "platform_specific": {
                          "soundcloud": {
                            "album_title": null,
                            "artist_name": "Forss",
                            "author_follower_count": 132108,
                            "c_line": null,
                            "caption": null,
                            "download_count": 21595,
                            "embeddable_by": "all",
                            "genre": "Electronic",
                            "is_commentable": true,
                            "is_downloadable": true,
                            "is_explicit": null,
                            "is_music": true,
                            "is_streamable": true,
                            "isrc": "DEP960300042",
                            "label_name": "sonarkollektiv",
                            "last_modified_at": "2022-07-11T10:55:58Z",
                            "license": "all-rights-reserved",
                            "monetization_model": "AD_SUPPORTED",
                            "p_line": null,
                            "permalink": "flickermood",
                            "policy": "MONETIZE",
                            "publisher": "Universal Music Publishing",
                            "purchase_title": null,
                            "purchase_url": "http://sonarkollektiv.com/tracks/DE-P96-03-00042",
                            "release_title": null,
                            "released_at": "2003-06-02T00:00:00Z",
                            "tags": [
                              "downtempo"
                            ],
                            "transcodings": [
                              {
                                "duration_ms": 213886,
                                "is_snipped": false,
                                "mime_type": "audio/mp4; codecs=\"mp4a.40.2\"",
                                "preset": "aac_160k",
                                "protocol": "hls",
                                "quality": "sq"
                              },
                              {
                                "duration_ms": 213886,
                                "is_snipped": false,
                                "mime_type": "audio/mp4; codecs=\"mp4a.40.2\"",
                                "preset": "aac_96k",
                                "protocol": "hls",
                                "quality": "lq"
                              },
                              {
                                "duration_ms": 213886,
                                "is_snipped": false,
                                "mime_type": "audio/mpegurl",
                                "preset": "abr_sq",
                                "protocol": "hls",
                                "quality": "sq"
                              }
                            ],
                            "upc": null,
                            "uploaded_at": "2007-09-22T14:45:46Z",
                            "visual_url": null,
                            "waveform_url": "https://wave.sndcdn.com/cWHNerOLlkUq_m.json",
                            "writer_composer": "Eric Wahlforss"
                          }
                        },
                        "platform_type": "track",
                        "published_at": "2007-09-22T14:45:46Z",
                        "text": "From the Soulhack album, recently featured in this ad https://www.dswshoes.com/tv_commercial.jsp?m=october2007",
                        "thumbnail_url": "https://i1.sndcdn.com/artworks-000067273316-smsiqx-t500x500.jpg",
                        "title": "Flickermood",
                        "type": "audio",
                        "unknown_fields": [],
                        "url": "https://soundcloud.com/forss/flickermood"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "soundcloud",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 287,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "293",
                          "url": "https://soundcloud.com/forss/flickermood"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SoundcloudTrackResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact plays, likes, reposts and ISRC",
        "tags": [
          "SoundCloud"
        ],
        "x-socialtap-endpoint": "soundcloud.track",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/soundcloud/tracks": {
      "get": {
        "description": "Returns a SoundCloud artist's public tracks, newest first, a page at a time, from its name, link, URN or ID. Each track has the same fields as the SoundCloud Track API: exact play, like, repost, comment and download counts, title, description, artwork, length, dates, genre, tags, license and the ISRC, label and UPC that labels fill in. Filter by date with since and until.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Post` items (SoundCloud calls it a track) (the shared schema, the same on every platform), newest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn SoundCloud's words: `metrics.view_count` is plays.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/soundcloud/tracks/ (Markdown: https://socialtap.dev/docs/reference/soundcloud/tracks/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/soundcloud/tracks/index.md)",
          "url": "https://socialtap.dev/docs/reference/soundcloud/tracks/"
        },
        "operationId": "soundcloud.tracks.list",
        "parameters": [
          {
            "description": "The SoundCloud account: its name (forss, also written @forss), its link (soundcloud.com/forss, with any tab such as /tracks, also on m.soundcloud.com), its numeric ID (183), URN (soundcloud:users:183) or address on the API (api.soundcloud.com/users/183). Names are case-insensitive.",
            "example": "forss",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The SoundCloud account: its name (forss, also written @forss), its link (soundcloud.com/forss, with any tab such as /tracks, also on m.soundcloud.com), its numeric ID (183), URN (soundcloud:users:183) or address on the API (api.soundcloud.com/users/183). Names are case-insensitive.",
              "examples": [
                "forss"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only tracks that went public at or after this time.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only tracks that went public at or after this time.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Only tracks that went public before this time. The walk starts there, so later tracks are not fetched or charged.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Only tracks that went public before this time. The walk starts there, so later tracks are not fetched or charged.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i1.sndcdn.com/avatars-000012778523-59quu3-t500x500.jpg",
                            "display_name": "Forss",
                            "id": "183",
                            "is_verified": true,
                            "url": "https://soundcloud.com/forss",
                            "username": "forss"
                          },
                          "coauthors": [],
                          "duration_ms": 370348,
                          "hashtags": [],
                          "id": "49438146",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 370201,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://i1.sndcdn.com/artworks-000024916496-q9opo6-t500x500.jpg",
                              "type": "audio",
                              "url": null,
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 408,
                            "like_count": 4707,
                            "quote_count": null,
                            "repost_count": 709,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 229618
                          },
                          "platform": "soundcloud",
                          "platform_specific": {
                            "soundcloud": {
                              "album_title": null,
                              "artist_name": "Forss",
                              "author_follower_count": 132108,
                              "c_line": null,
                              "caption": null,
                              "download_count": 1,
                              "embeddable_by": "all",
                              "genre": "Electronic",
                              "is_commentable": true,
                              "is_downloadable": false,
                              "is_explicit": null,
                              "is_music": true,
                              "is_streamable": true,
                              "isrc": "TCABG1298306",
                              "label_name": null,
                              "last_modified_at": "2022-04-25T07:14:56Z",
                              "license": "all-rights-reserved",
                              "monetization_model": "AD_SUPPORTED",
                              "p_line": null,
                              "permalink": "lux-aeterna",
                              "policy": "MONETIZE",
                              "publisher": "Eric Wahlforss",
                              "purchase_title": "Get The App",
                              "purchase_url": "http://itunes.com/app/ecclesia",
                              "release_title": null,
                              "released_at": "2012-06-12T00:00:00Z",
                              "tags": [],
                              "transcodings": [
                                {
                                  "duration_ms": 370201,
                                  "is_snipped": false,
                                  "mime_type": "audio/mp4; codecs=\"mp4a.40.2\"",
                                  "preset": "aac_160k",
                                  "protocol": "hls",
                                  "quality": "sq"
                                },
                                {
                                  "duration_ms": 370201,
                                  "is_snipped": false,
                                  "mime_type": "audio/mp4; codecs=\"mp4a.40.2\"",
                                  "preset": "aac_96k",
                                  "protocol": "hls",
                                  "quality": "lq"
                                },
                                {
                                  "duration_ms": 370201,
                                  "is_snipped": false,
                                  "mime_type": "audio/mpegurl",
                                  "preset": "abr_sq",
                                  "protocol": "hls",
                                  "quality": "sq"
                                }
                              ],
                              "upc": null,
                              "uploaded_at": "2012-06-12T11:29:55Z",
                              "visual_url": null,
                              "waveform_url": "https://wave.sndcdn.com/RhJ436DPf2Vx_m.json",
                              "writer_composer": "Eric Wahlforss"
                            }
                          },
                          "platform_type": "track",
                          "published_at": "2012-06-12T11:29:55Z",
                          "text": "Tenth piece from the Ecclesia project.\r\n\r\nProduction: Eric Wahlforss\r\nMixing: Mark Bihler\r\nMastering: Bo Kondren",
                          "thumbnail_url": "https://i1.sndcdn.com/artworks-000024916496-q9opo6-t500x500.jpg",
                          "title": "Lux Aeterna",
                          "type": "audio",
                          "unknown_fields": [],
                          "url": "https://soundcloud.com/forss/lux-aeterna"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i1.sndcdn.com/avatars-000012778523-59quu3-t500x500.jpg",
                            "display_name": "Forss",
                            "id": "183",
                            "is_verified": true,
                            "url": "https://soundcloud.com/forss",
                            "username": "forss"
                          },
                          "coauthors": [],
                          "duration_ms": 68127,
                          "hashtags": [],
                          "id": "49437906",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 68095,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://i1.sndcdn.com/artworks-000024916399-ov6bex-t500x500.jpg",
                              "type": "audio",
                              "url": null,
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 79,
                            "like_count": 491,
                            "quote_count": null,
                            "repost_count": 89,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 50349
                          },
                          "platform": "soundcloud",
                          "platform_specific": {
                            "soundcloud": {
                              "album_title": null,
                              "artist_name": "Forss",
                              "author_follower_count": 132108,
                              "c_line": null,
                              "caption": null,
                              "download_count": 0,
                              "embeddable_by": "all",
                              "genre": "Electronic",
                              "is_commentable": true,
                              "is_downloadable": false,
                              "is_explicit": null,
                              "is_music": true,
                              "is_streamable": true,
                              "isrc": "TCABG1298305",
                              "label_name": null,
                              "last_modified_at": "2019-07-29T16:43:49Z",
                              "license": "all-rights-reserved",
                              "monetization_model": "AD_SUPPORTED",
                              "p_line": null,
                              "permalink": "veniam",
                              "policy": "MONETIZE",
                              "publisher": "Eric Wahlforss",
                              "purchase_title": "Get The App",
                              "purchase_url": "http://itunes.com/app/ecclesia",
                              "release_title": null,
                              "released_at": "2012-06-12T00:00:00Z",
                              "tags": [],
                              "transcodings": [
                                {
                                  "duration_ms": 68095,
                                  "is_snipped": false,
                                  "mime_type": "audio/mp4; codecs=\"mp4a.40.2\"",
                                  "preset": "aac_160k",
                                  "protocol": "hls",
                                  "quality": "sq"
                                },
                                {
                                  "duration_ms": 68095,
                                  "is_snipped": false,
                                  "mime_type": "audio/mp4; codecs=\"mp4a.40.2\"",
                                  "preset": "aac_96k",
                                  "protocol": "hls",
                                  "quality": "lq"
                                },
                                {
                                  "duration_ms": 68095,
                                  "is_snipped": false,
                                  "mime_type": "audio/mpegurl",
                                  "preset": "abr_sq",
                                  "protocol": "hls",
                                  "quality": "sq"
                                }
                              ],
                              "upc": null,
                              "uploaded_at": "2012-06-12T11:26:04Z",
                              "visual_url": null,
                              "waveform_url": "https://wave.sndcdn.com/DWpqP6aFqglm_m.json",
                              "writer_composer": "Eric Wahlforss"
                            }
                          },
                          "platform_type": "track",
                          "published_at": "2012-06-12T11:26:04Z",
                          "text": "Ninth piece from the Ecclesia project.\r\n\r\nProduction: Eric Wahlforss\r\nMixing: Mark Bihler\r\nMastering: Bo Kondren",
                          "thumbnail_url": "https://i1.sndcdn.com/artworks-000024916399-ov6bex-t500x500.jpg",
                          "title": "Veniam",
                          "type": "audio",
                          "unknown_fields": [],
                          "url": "https://soundcloud.com/forss/veniam"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i1.sndcdn.com/avatars-000012778523-59quu3-t500x500.jpg",
                            "display_name": "Forss",
                            "id": "183",
                            "is_verified": true,
                            "url": "https://soundcloud.com/forss",
                            "username": "forss"
                          },
                          "coauthors": [],
                          "duration_ms": 326183,
                          "hashtags": [],
                          "id": "48031525",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 326054,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://i1.sndcdn.com/artworks-000024190525-pv7oaf-t500x500.jpg",
                              "type": "audio",
                              "url": null,
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 115,
                            "like_count": 1156,
                            "quote_count": null,
                            "repost_count": 173,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 61203
                          },
                          "platform": "soundcloud",
                          "platform_specific": {
                            "soundcloud": {
                              "album_title": null,
                              "artist_name": "Forss",
                              "author_follower_count": 132108,
                              "c_line": null,
                              "caption": null,
                              "download_count": 0,
                              "embeddable_by": "all",
                              "genre": "Electronic",
                              "is_commentable": true,
                              "is_downloadable": false,
                              "is_explicit": null,
                              "is_music": true,
                              "is_streamable": true,
                              "isrc": "TCABG1298304",
                              "label_name": null,
                              "last_modified_at": "2021-06-28T10:35:35Z",
                              "license": "all-rights-reserved",
                              "monetization_model": "AD_SUPPORTED",
                              "p_line": null,
                              "permalink": "somnio-somnium",
                              "policy": "MONETIZE",
                              "publisher": "Eric Wahlforss",
                              "purchase_title": "Get The App",
                              "purchase_url": "http://itunes.com/app/ecclesia",
                              "release_title": null,
                              "released_at": null,
                              "tags": [],
                              "transcodings": [
                                {
                                  "duration_ms": 326054,
                                  "is_snipped": false,
                                  "mime_type": "audio/mp4; codecs=\"mp4a.40.2\"",
                                  "preset": "aac_160k",
                                  "protocol": "hls",
                                  "quality": "sq"
                                },
                                {
                                  "duration_ms": 326054,
                                  "is_snipped": false,
                                  "mime_type": "audio/mp4; codecs=\"mp4a.40.2\"",
                                  "preset": "aac_96k",
                                  "protocol": "hls",
                                  "quality": "lq"
                                },
                                {
                                  "duration_ms": 326054,
                                  "is_snipped": false,
                                  "mime_type": "audio/mpegurl",
                                  "preset": "abr_sq",
                                  "protocol": "hls",
                                  "quality": "sq"
                                }
                              ],
                              "upc": null,
                              "uploaded_at": "2012-05-30T08:13:11Z",
                              "visual_url": null,
                              "waveform_url": "https://wave.sndcdn.com/sDWnMpZaIQ9Z_m.json",
                              "writer_composer": "Eric Wahlforss"
                            }
                          },
                          "platform_type": "track",
                          "published_at": "2012-05-30T08:13:11Z",
                          "text": "Eighth piece from the Ecclesia project.\r\n\r\nProduction: Eric Wahlforss \r\nMixing: Mark Bihler \r\nMastering: Bo Kondren\r\n\r\nContains a sample from Eric Whitacre's 'Sleep My Child SATB version' https://soundcloud.com/ericwhitacre/sleep-my-child-satb-a-cappella",
                          "thumbnail_url": "https://i1.sndcdn.com/artworks-000024190525-pv7oaf-t500x500.jpg",
                          "title": "Somnio Somnium",
                          "type": "audio",
                          "unknown_fields": [],
                          "url": "https://soundcloud.com/forss/somnio-somnium"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "soundcloud",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 518,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "183",
                          "url": "https://soundcloud.com/forss"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SoundcloudTracksResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Newest first, with exact plays and ISRC",
        "tags": [
          "SoundCloud"
        ],
        "x-socialtap-endpoint": "soundcloud.tracks",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/spotify/album": {
      "get": {
        "description": "Returns a public Spotify album, single or EP from its link, share link, URI or ID, with its full tracklist and each track's exact play count. It also has the label, UPC, copyright lines, release date, cover, credited artists, total length, popularity score and explicit flag.\n\nReturns `{data, meta}`: `data` is a `Album` object (the shared schema, the same on every platform). Null means unknown.\n\nIn Spotify's words: `tracks[].metrics.view_count` is plays.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/spotify/album/ (Markdown: https://socialtap.dev/docs/reference/spotify/album/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/spotify/album/index.md)",
          "url": "https://socialtap.dev/docs/reference/spotify/album/"
        },
        "operationId": "spotify.album.get",
        "parameters": [
          {
            "description": "The release: its link (open.spotify.com/album/6N9PS4QXF1D0OWPk0Sxtb4, also under /intl-de/ and /embed/, with any share parameters), a share link (spotify.link/…), its URI (spotify:album:6N9PS4QXF1D0OWPk0Sxtb4) or its 22-character ID.",
            "example": "https://open.spotify.com/album/6N9PS4QXF1D0OWPk0Sxtb4",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The release: its link (open.spotify.com/album/6N9PS4QXF1D0OWPk0Sxtb4, also under /intl-de/ and /embed/, with any share parameters), a share link (spotify.link/…), its URI (spotify:album:6N9PS4QXF1D0OWPk0Sxtb4) or its 22-character ID.",
              "examples": [
                "https://open.spotify.com/album/6N9PS4QXF1D0OWPk0Sxtb4"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "released_at"
                        ],
                        "artist_name": "Rick Astley",
                        "artists": [
                          {
                            "avatar_url": "https://i.scdn.co/image/ab6761610000e5eb854861dff9a24a1ed3dfdc7d",
                            "display_name": "Rick Astley",
                            "id": "0gxyHStUsqpMadRV0Di1Qt",
                            "is_verified": null,
                            "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                            "username": null
                          }
                        ],
                        "copyrights": [
                          {
                            "text": "(P) 1987 Sony Music Entertainment UK Limited under exclusive license to BMG Rights Management (UK) Limited",
                            "type": "p"
                          }
                        ],
                        "cover_url": "https://i.scdn.co/image/ab67616d0000b273255e131abc1410833be95673",
                        "description": null,
                        "duration_ms": 2214250,
                        "genres": [],
                        "id": "6N9PS4QXF1D0OWPk0Sxtb4",
                        "is_explicit": false,
                        "label": "Sony Music CG",
                        "metrics": {
                          "track_count": 10
                        },
                        "platform": "spotify",
                        "platform_specific": {
                          "spotify": {
                            "is_playable": true,
                            "is_pre_release": false,
                            "popularity": 3,
                            "pre_release_ends_at": null,
                            "release_date_precision": "day"
                          }
                        },
                        "released_at": "1987-11-12T00:00:00Z",
                        "title": "Whenever You Need Somebody",
                        "tracks": [
                          {
                            "artist_name": "Rick Astley",
                            "artists": [
                              {
                                "avatar_url": null,
                                "display_name": "Rick Astley",
                                "id": "0gxyHStUsqpMadRV0Di1Qt",
                                "is_verified": null,
                                "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                                "username": null
                              }
                            ],
                            "disc_number": 1,
                            "duration_ms": 213573,
                            "id": "4uLU6hMCjMI75M1A2tKUQC",
                            "is_explicit": false,
                            "isrc": null,
                            "metrics": {
                              "view_count": 1200207819
                            },
                            "play_url": "https://p.scdn.co/mp3-preview/40a780b231e5ed130483bec7917b6c9a4f8a4708",
                            "title": "Never Gonna Give You Up",
                            "track_number": 1,
                            "url": "https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC"
                          },
                          {
                            "artist_name": "Rick Astley",
                            "artists": [
                              {
                                "avatar_url": null,
                                "display_name": "Rick Astley",
                                "id": "0gxyHStUsqpMadRV0Di1Qt",
                                "is_verified": null,
                                "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                                "username": null
                              }
                            ],
                            "disc_number": 1,
                            "duration_ms": 233666,
                            "id": "6aiKIFjPwa3UvDCD5ecoJj",
                            "is_explicit": false,
                            "isrc": null,
                            "metrics": {
                              "view_count": 24633284
                            },
                            "play_url": "https://p.scdn.co/mp3-preview/0882466928469699e0e06e4f3c2fe4904bb5e238",
                            "title": "Whenever You Need Somebody",
                            "track_number": 2,
                            "url": "https://open.spotify.com/track/6aiKIFjPwa3UvDCD5ecoJj"
                          },
                          {
                            "artist_name": "Rick Astley",
                            "artists": [
                              {
                                "avatar_url": null,
                                "display_name": "Rick Astley",
                                "id": "0gxyHStUsqpMadRV0Di1Qt",
                                "is_verified": null,
                                "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                                "username": null
                              }
                            ],
                            "disc_number": 1,
                            "duration_ms": 205533,
                            "id": "76QJgXPE3oc1cnkE4PFHEn",
                            "is_explicit": false,
                            "isrc": null,
                            "metrics": {
                              "view_count": 218756612
                            },
                            "play_url": "https://p.scdn.co/mp3-preview/232347ea8e18d9cc6e7df7d227dbe98d7d999f36",
                            "title": "Together Forever",
                            "track_number": 3,
                            "url": "https://open.spotify.com/track/76QJgXPE3oc1cnkE4PFHEn"
                          }
                        ],
                        "type": "album",
                        "unknown_fields": [
                          "genres"
                        ],
                        "upc": "035627515026",
                        "url": "https://open.spotify.com/album/6N9PS4QXF1D0OWPk0Sxtb4"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "spotify",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 543,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "album",
                          "id": "6N9PS4QXF1D0OWPk0Sxtb4",
                          "url": "https://open.spotify.com/album/6N9PS4QXF1D0OWPk0Sxtb4"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SpotifyAlbumResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Full tracklist with plays, label and UPC",
        "tags": [
          "Spotify"
        ],
        "x-socialtap-endpoint": "spotify.album",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "album",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/spotify/artist": {
      "get": {
        "description": "Returns a public Spotify artist from its link, URI or ID, with exact followers, monthly listeners, world rank and the top cities its listeners are in. It also has the bio, pictures, verified badge, top tracks with their plays, every release ID in its discography, related artists, upcoming concerts, playlists and the links on its profile.\n\nReturns `{data, meta}`: `data` is a `Profile` object (Spotify calls it a artist) (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/spotify/artist/ (Markdown: https://socialtap.dev/docs/reference/spotify/artist/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/spotify/artist/index.md)",
          "url": "https://socialtap.dev/docs/reference/spotify/artist/"
        },
        "operationId": "spotify.artist.get",
        "parameters": [
          {
            "description": "The artist: its link (open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt, also under /intl-de/ or /embed/, on any tab such as /discography/all or /about, with any share parameters), its URI (spotify:artist:0gxyHStUsqpMadRV0Di1Qt) or its 22-character ID. A listener's username or /user/ link is refused: this endpoint answers artists. A share link (spotify.link/…) is not read here: pass what it leads to.",
            "example": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The artist: its link (open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt, also under /intl-de/ or /embed/, on any tab such as /discography/all or /about, with any share parameters), its URI (spotify:artist:0gxyHStUsqpMadRV0Di1Qt) or its 22-character ID. A listener's username or /user/ link is refused: this endpoint answers artists. A share link (spotify.link/…) is not read here: pass what it leads to.",
              "examples": [
                "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "platform_specific.spotify.latest_release.released_at",
                          "platform_specific.spotify.popular_releases[].released_at",
                          "platform_specific.spotify.albums.items[].released_at"
                        ],
                        "avatar_url": "https://i.scdn.co/image/ab6761610000e5eb854861dff9a24a1ed3dfdc7d",
                        "banner_url": "https://image-cdn-fa.spotifycdn.com/image/ab6761860000eab11c3a6e7e0cc5ec4e130bbdef",
                        "bio": "It’s one of contemporary music’s most unlikely tales. At the age of 21, Rick Astley emerged from the shadows of the Stock, Aitken and Waterman production house as their former tea boy became one of the biggest stars on the planet. His era-defining classic ‘Never Gonna Give You Up…",
                        "category": null,
                        "country_code": null,
                        "created_at": null,
                        "display_name": "Rick Astley",
                        "external_links": [
                          {
                            "title": "FACEBOOK",
                            "url": "https://facebook.com/RickAstley"
                          },
                          {
                            "title": "INSTAGRAM",
                            "url": "https://instagram.com/officialrickastley"
                          },
                          {
                            "title": "TIKTOK",
                            "url": "https://tiktok.com/@rickastleyofficial"
                          }
                        ],
                        "id": "0gxyHStUsqpMadRV0Di1Qt",
                        "is_private": null,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 1631120,
                          "following_count": null,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "spotify",
                        "platform_specific": {
                          "spotify": {
                            "active_decades": [
                              2000,
                              1990,
                              1980
                            ],
                            "ai_persona": null,
                            "albums": {
                              "ids": [
                                "2WlZ6L68eq4Wy7QUSI2ffK",
                                "5vIhE61ppC6YyGaM5S4yJD"
                              ],
                              "items": [
                                {
                                  "artists": [],
                                  "cover_url": "https://i.scdn.co/image/ab67616d0000b27302f0b93ecab5bad9a8224b40",
                                  "id": "2WlZ6L68eq4Wy7QUSI2ffK",
                                  "label": "BMG Rights Management GmbH",
                                  "release_date_precision": "day",
                                  "released_at": "2026-06-15T00:00:00Z",
                                  "title": "50 (10th Anniversary Deluxe Edition)",
                                  "track_count": 15,
                                  "type": "album",
                                  "url": "https://open.spotify.com/album/2WlZ6L68eq4Wy7QUSI2ffK"
                                }
                              ],
                              "total_count": 12
                            },
                            "appears_on": {
                              "ids": [
                                "4FLE3sQpCWW9zwB1HE7erQ",
                                "2dEe2RBqwaeKWdmZ5FBlL6"
                              ],
                              "items": [
                                {
                                  "artists": [
                                    {
                                      "avatar_url": null,
                                      "display_name": "Various Artists",
                                      "id": "0LyfQWJT6nXafLPZqxe9Of",
                                      "is_verified": null,
                                      "url": "https://open.spotify.com/artist/0LyfQWJT6nXafLPZqxe9Of",
                                      "username": null
                                    }
                                  ],
                                  "cover_url": "https://i.scdn.co/image/ab67616d0000b273068ba75bb02a2be71316631b",
                                  "id": "2dEe2RBqwaeKWdmZ5FBlL6",
                                  "label": null,
                                  "release_date_precision": "year",
                                  "released_at": "2024-01-01T00:00:00Z",
                                  "title": "Songs for Mum",
                                  "track_count": null,
                                  "type": "compilation",
                                  "url": "https://open.spotify.com/album/2dEe2RBqwaeKWdmZ5FBlL6"
                                }
                              ],
                              "total_count": 20
                            },
                            "biography_type": "autobiography",
                            "compilations": {
                              "ids": [
                                "6C55u1I4oqut6X97zIh8m4",
                                "6CWdaSQN5rsdDkOrhFcZ0E"
                              ],
                              "items": [
                                {
                                  "artists": [],
                                  "cover_url": "https://i.scdn.co/image/ab67616d0000b273ad292ed19701d9f5c8cf71b6",
                                  "id": "6CWdaSQN5rsdDkOrhFcZ0E",
                                  "label": "BMG Rights Management (UK) Ltd.",
                                  "release_date_precision": "day",
                                  "released_at": "2019-12-29T00:00:00Z",
                                  "title": "The Best of Me",
                                  "track_count": 31,
                                  "type": "compilation",
                                  "url": "https://open.spotify.com/album/6CWdaSQN5rsdDkOrhFcZ0E"
                                }
                              ],
                              "total_count": 3
                            },
                            "concert_count": 5,
                            "concerts": [
                              {
                                "city": "London",
                                "id": "6Uk6FeW4q5sOpJIEdGs4iY",
                                "is_festival": false,
                                "starts_at": "2026-12-09T18:45:00Z",
                                "title": "Rick Astley",
                                "url": "https://open.spotify.com/concert/6Uk6FeW4q5sOpJIEdGs4iY",
                                "venue": "Royal Albert Hall"
                              }
                            ],
                            "discovered_on": [
                              {
                                "description": null,
                                "id": "0A9tWS2qryvdrFJBObAque",
                                "image_url": "https://mosaic.scdn.co/640/ab67616d00001e023e030a7e606959674643d274ab67616d00001e02c7d7cdad0c2ffa5620129ee8ab67616d00001e02c8e97cafeb2acb85b21a777eab67616d00001e02e8dd4db47e7177c63b0b7d53",
                                "owner_name": "fld5wrzio6qv6nus8yln7v71o",
                                "title": "Mix 80's , 90's y 2000's en inglés",
                                "url": "https://open.spotify.com/playlist/0A9tWS2qryvdrFJBObAque"
                              }
                            ],
                            "discovered_on_count": 100,
                            "featured_in": [
                              {
                                "description": "This is Rick Astley. The essential tracks, all in one playlist.",
                                "id": "37i9dQZF1DZ06evO05tE88",
                                "image_url": "https://pickasso.spotifycdn.com/image/ab67c0de0000deef/dt/v1/img/thisisv3/0gxyHStUsqpMadRV0Di1Qt/en",
                                "owner_name": "Spotify",
                                "title": "This Is Rick Astley",
                                "url": "https://open.spotify.com/playlist/37i9dQZF1DZ06evO05tE88"
                              }
                            ],
                            "featured_in_count": 8,
                            "gallery_urls": [
                              "https://i.scdn.co/image/ab6761670000ecd4aa3dfc611956e0cefd014e13"
                            ],
                            "is_registered": true,
                            "latest_release": {
                              "artists": [],
                              "cover_url": "https://i.scdn.co/image/ab67616d0000b27302f0b93ecab5bad9a8224b40",
                              "id": "2WlZ6L68eq4Wy7QUSI2ffK",
                              "label": "BMG Rights Management GmbH",
                              "release_date_precision": "day",
                              "released_at": "2026-06-15T00:00:00Z",
                              "title": "50 (10th Anniversary Deluxe Edition)",
                              "track_count": 15,
                              "type": "album",
                              "url": "https://open.spotify.com/album/2WlZ6L68eq4Wy7QUSI2ffK"
                            },
                            "monthly_listener_count": 8585233,
                            "music_video_count": 45,
                            "music_videos": [
                              {
                                "album_id": "1BaML8N5XYn1jgopz6Em2V",
                                "artist_name": "Rick Astley",
                                "artists": [
                                  {
                                    "avatar_url": null,
                                    "display_name": "Rick Astley",
                                    "id": "0gxyHStUsqpMadRV0Di1Qt",
                                    "is_verified": null,
                                    "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                                    "username": null
                                  }
                                ],
                                "cover_url": "https://i.scdn.co/image/ab6742d3000053b7ca75989d214a6838ec755e38",
                                "disc_number": null,
                                "duration_ms": null,
                                "id": "7BTWdRIS8yVo1urCff7X2G",
                                "is_explicit": false,
                                "play_count": null,
                                "title": "Never Gonna Give You Up - Pianoforte",
                                "url": "https://open.spotify.com/track/7BTWdRIS8yVo1urCff7X2G"
                              }
                            ],
                            "pinned_item": {
                              "comment": "Including three new live performances!",
                              "image_url": "https://image-cdn-ak.spotifycdn.com/image/ab67616d000075a002f0b93ecab5bad9a8224b40",
                              "subtitle": "Album",
                              "title": "50 (10th Anniversary Deluxe Edition)",
                              "type": "album",
                              "uri": "spotify:album:2WlZ6L68eq4Wy7QUSI2ffK"
                            },
                            "playlist_count": 5,
                            "playlists": [
                              {
                                "description": "In celebration of the 10th anniversary of Rick Astley's album '50', relive the 50 Tour here.",
                                "id": "2rgXjEciA1zacD1IjVg5nV",
                                "image_url": "https://image-cdn-fa.spotifycdn.com/image/ab67706c0000d72cb5852cc9d3dc2ce4c05d514f",
                                "owner_name": "Rick Astley",
                                "title": "50 Tour Set List",
                                "url": "https://open.spotify.com/playlist/2rgXjEciA1zacD1IjVg5nV"
                              }
                            ],
                            "popular_release_count": 20,
                            "popular_releases": [
                              {
                                "artists": [],
                                "cover_url": "https://i.scdn.co/image/ab67616d0000b2733a67639779ccabd632e1a80e",
                                "id": "4C4LvbYS0pxXLW5sGD9EK5",
                                "label": "BMG Rights Management (UK) Ltd.",
                                "release_date_precision": "day",
                                "released_at": "2022-05-20T00:00:00Z",
                                "title": "Whenever You Need Somebody (Deluxe Edition - 2022 Remaster)",
                                "track_count": 36,
                                "type": "album",
                                "url": "https://open.spotify.com/album/4C4LvbYS0pxXLW5sGD9EK5"
                              }
                            ],
                            "popularity": 67,
                            "related_artist_count": 40,
                            "related_artists": [
                              {
                                "avatar_url": "https://i.scdn.co/image/ab6761610000e5eb373b4aa8b6b5ca058a67307f",
                                "display_name": "Culture Club",
                                "id": "6kz53iCdBSqhQCZ21CoLcc",
                                "is_verified": null,
                                "url": "https://open.spotify.com/artist/6kz53iCdBSqhQCZ21CoLcc",
                                "username": null
                              }
                            ],
                            "singles": {
                              "ids": [
                                "0xOvvd9BQwlhJTnKfgB2zz",
                                "5U0RVHlHR4ywoPiOxosTgv"
                              ],
                              "items": [
                                {
                                  "artists": [],
                                  "cover_url": "https://i.scdn.co/image/ab67616d0000b273fe8a8d62b127592ff546d9c8",
                                  "id": "0xOvvd9BQwlhJTnKfgB2zz",
                                  "label": "BMG Rights Management (UK) Ltd.",
                                  "release_date_precision": "day",
                                  "released_at": "2026-04-10T00:00:00Z",
                                  "title": "Raindrops",
                                  "track_count": 2,
                                  "type": "single",
                                  "url": "https://open.spotify.com/album/0xOvvd9BQwlhJTnKfgB2zz"
                                }
                              ],
                              "total_count": 44
                            },
                            "top_cities": [
                              {
                                "city": "Mexico City",
                                "country_code": "MX",
                                "listener_count": 197397,
                                "region": "CMX"
                              }
                            ],
                            "top_tracks": [
                              {
                                "album_id": "4C4LvbYS0pxXLW5sGD9EK5",
                                "artist_name": "Rick Astley",
                                "artists": [
                                  {
                                    "avatar_url": null,
                                    "display_name": "Rick Astley",
                                    "id": "0gxyHStUsqpMadRV0Di1Qt",
                                    "is_verified": null,
                                    "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                                    "username": null
                                  }
                                ],
                                "cover_url": "https://i.scdn.co/image/ab67616d00001e023a67639779ccabd632e1a80e",
                                "disc_number": 1,
                                "duration_ms": 213560,
                                "id": "0yNttAVwMr39qyODHNIkrY",
                                "is_explicit": false,
                                "play_count": 1200625029,
                                "title": "Never Gonna Give You Up - 2022 Remaster",
                                "url": "https://open.spotify.com/track/0yNttAVwMr39qyODHNIkrY"
                              }
                            ],
                            "world_rank": null
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                        "username": null
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "spotify",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 639,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "0gxyHStUsqpMadRV0Di1Qt",
                          "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SpotifyArtistResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Monthly listeners, top cities and releases",
        "tags": [
          "Spotify"
        ],
        "x-socialtap-endpoint": "spotify.artist",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/spotify/playlist": {
      "get": {
        "description": "Returns a public Spotify playlist from its link, share link, URI or ID, with its exact follower count, owner, item count and when it was last changed. It also has the title, description, cover, creation date, whether it is collaborative, and whether it is Spotify's own and made by its algorithm. The Spotify Playlist Tracks API returns its tracks.\n\nReturns `{data, meta}`: `data` is a `Playlist` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/spotify/playlist/ (Markdown: https://socialtap.dev/docs/reference/spotify/playlist/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/spotify/playlist/index.md)",
          "url": "https://socialtap.dev/docs/reference/spotify/playlist/"
        },
        "operationId": "spotify.playlist.get",
        "parameters": [
          {
            "description": "The playlist: its link (open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M, also under /intl-de/ and /embed/, the old /user/<name>/playlist/… form, with any share parameters), a share link (spotify.link/…), its URI (spotify:playlist:37i9dQZF1DXcBWIGoYBM5M, or the old spotify:user:<name>:playlist:…) or its 22-character ID.",
            "example": "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The playlist: its link (open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M, also under /intl-de/ and /embed/, the old /user/<name>/playlist/… form, with any share parameters), a share link (spotify.link/…), its URI (spotify:playlist:37i9dQZF1DXcBWIGoYBM5M, or the old spotify:user:<name>:playlist:…) or its 22-character ID.",
              "examples": [
                "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "description": "The hottest 50. Cover: Tame Impala",
                        "id": "37i9dQZF1DXcBWIGoYBM5M",
                        "is_collaborative": false,
                        "metrics": {
                          "post_count": 50
                        },
                        "owner": {
                          "avatar_url": "https://i.scdn.co/image/ab6775700000ee8555c25988a6ac314394d3fbf5",
                          "display_name": "Spotify",
                          "id": null,
                          "is_verified": null,
                          "url": "https://open.spotify.com/user/spotify",
                          "username": "spotify"
                        },
                        "platform": "spotify",
                        "platform_specific": {
                          "spotify": {
                            "created_at": null,
                            "follower_count": 33626571,
                            "is_algorithmic": false,
                            "is_collaborative": false,
                            "is_deleted_by_owner": false,
                            "is_user_created": false,
                            "updated_at": "2026-10-30T04:01:22Z"
                          }
                        },
                        "platform_type": "playlist",
                        "thumbnail_url": "https://i.scdn.co/image/ab67706f00000002960019ea66cba66a44fdd4c2",
                        "title": "Today’s Top Hits",
                        "type": "playlist",
                        "unknown_fields": [],
                        "url": "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "spotify",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 317,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "playlist",
                          "id": "37i9dQZF1DXcBWIGoYBM5M",
                          "url": "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SpotifyPlaylistResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact followers, owner and last update",
        "tags": [
          "Spotify"
        ],
        "x-socialtap-endpoint": "spotify.playlist",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "playlist",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/spotify/playlist_tracks": {
      "get": {
        "description": "Returns the tracks of a public Spotify playlist in its own order, a page at a time, from its link, share link, URI or ID. Each track has its artists, album, release date, length, exact play count, preview clip, who added it and when, and its BPM, key and Camelot key.\n\nReturns `{data, page, meta}`: `data` holds up to 100 `Post` items (Spotify calls it a track) (the shared schema, the same on every platform), the playlist's own order, as its owner or Spotify arranged it. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Spotify's words: `metrics.view_count` is plays.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/spotify/playlist_tracks/ (Markdown: https://socialtap.dev/docs/reference/spotify/playlist_tracks/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/spotify/playlist_tracks/index.md)",
          "url": "https://socialtap.dev/docs/reference/spotify/playlist_tracks/"
        },
        "operationId": "spotify.playlist_tracks.list",
        "parameters": [
          {
            "description": "The playlist: its link (open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M, also under /intl-de/ and /embed/, the old /user/<name>/playlist/… form, with any share parameters), a share link (spotify.link/…), its URI (spotify:playlist:37i9dQZF1DXcBWIGoYBM5M, or the old spotify:user:<name>:playlist:…) or its 22-character ID.",
            "example": "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The playlist: its link (open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M, also under /intl-de/ and /embed/, the old /user/<name>/playlist/… form, with any share parameters), a share link (spotify.link/…), its URI (spotify:playlist:37i9dQZF1DXcBWIGoYBM5M, or the old spotify:user:<name>:playlist:…) or its 22-character ID.",
              "examples": [
                "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 100,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": null,
                            "display_name": "Tame Impala",
                            "id": "5INjqkS1o8h1imAzPqGZBb",
                            "is_verified": null,
                            "url": "https://open.spotify.com/artist/5INjqkS1o8h1imAzPqGZBb",
                            "username": null
                          },
                          "coauthors": [],
                          "duration_ms": 223069,
                          "hashtags": [],
                          "id": "7bxaFZ1O3cHkgLKMsdC3xR",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://i.scdn.co/image/ab67616d0000b273208500450dcd0fd294d7bd3b",
                              "type": "audio",
                              "url": "https://p.scdn.co/mp3-preview/0015e9347a45b62215447eba657b2fc3ce279d2d",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 380095374
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "added_at": "2026-08-07T04:02:23Z",
                              "added_by": null,
                              "album_id": "5WulAOx9ilWy1h8UGZ1gkI",
                              "album_title": "Deadbeat",
                              "album_track_count": null,
                              "album_type": null,
                              "album_url": "https://open.spotify.com/album/5WulAOx9ilWy1h8UGZ1gkI",
                              "bpm": 82.96,
                              "camelot_key": "4A",
                              "canonical_track_id": null,
                              "copyrights": [],
                              "credits": [],
                              "disc_number": 1,
                              "is_explicit": true,
                              "is_paywalled": null,
                              "is_playable": true,
                              "isrc": null,
                              "label": null,
                              "languages": [],
                              "music_video_count": 1,
                              "musical_key": "F minor",
                              "playability_reason": "playable",
                              "podcast_id": null,
                              "popularity": null,
                              "release_date_precision": "day",
                              "track_number": 4
                            }
                          },
                          "platform_type": "track",
                          "published_at": "2025-10-17T00:00:00Z",
                          "text": null,
                          "thumbnail_url": "https://i.scdn.co/image/ab67616d0000b273208500450dcd0fd294d7bd3b",
                          "title": "Loser",
                          "type": "audio",
                          "unknown_fields": [
                            "platform_specific.spotify.copyrights",
                            "platform_specific.spotify.credits",
                            "platform_specific.spotify.languages"
                          ],
                          "url": "https://open.spotify.com/track/7bxaFZ1O3cHkgLKMsdC3xR"
                        },
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": null,
                            "display_name": "Tate McRae",
                            "id": "45dkTj5sMRSjrmBSBeiHym",
                            "is_verified": null,
                            "url": "https://open.spotify.com/artist/45dkTj5sMRSjrmBSBeiHym",
                            "username": null
                          },
                          "coauthors": [],
                          "duration_ms": 208810,
                          "hashtags": [],
                          "id": "2sFepQNyl1WjpROruP8bJ0",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://i.scdn.co/image/ab67616d0000b273f2d3185e46b03c243f60ce53",
                              "type": "audio",
                              "url": "https://p.scdn.co/mp3-preview/724b097d9dc53e0541de27d199adfe3f610944ba",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 132138450
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "added_at": "2026-10-16T04:01:13Z",
                              "added_by": null,
                              "album_id": "6JvmSyocXef7RZDZFaymNl",
                              "album_title": "Housewife",
                              "album_track_count": null,
                              "album_type": null,
                              "album_url": "https://open.spotify.com/album/6JvmSyocXef7RZDZFaymNl",
                              "bpm": 132.99,
                              "camelot_key": "1A",
                              "canonical_track_id": null,
                              "copyrights": [],
                              "credits": [],
                              "disc_number": 1,
                              "is_explicit": false,
                              "is_paywalled": null,
                              "is_playable": true,
                              "isrc": null,
                              "label": null,
                              "languages": [],
                              "music_video_count": 1,
                              "musical_key": "G# minor",
                              "playability_reason": "playable",
                              "podcast_id": null,
                              "popularity": null,
                              "release_date_precision": "day",
                              "track_number": 1
                            }
                          },
                          "platform_type": "track",
                          "published_at": "2026-10-15T00:00:00Z",
                          "text": null,
                          "thumbnail_url": "https://i.scdn.co/image/ab67616d0000b273f2d3185e46b03c243f60ce53",
                          "title": "Housewife",
                          "type": "audio",
                          "unknown_fields": [
                            "platform_specific.spotify.copyrights",
                            "platform_specific.spotify.credits",
                            "platform_specific.spotify.languages"
                          ],
                          "url": "https://open.spotify.com/track/2sFepQNyl1WjpROruP8bJ0"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "spotify",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 597,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "playlist",
                          "id": "37i9dQZF1DXcBWIGoYBM5M",
                          "url": "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SpotifyPlaylist_tracksResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Plays, BPM, Camelot key and date added",
        "tags": [
          "Spotify"
        ],
        "x-socialtap-endpoint": "spotify.playlist_tracks",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the playlist's own order, as its owner or Spotify arranged it",
          "page_max": 100,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/spotify/podcast": {
      "get": {
        "description": "Returns a public Spotify podcast from its link, share link, URI or ID, with its exact average rating, number of ratings and episode count. It also has the name, description, publisher, cover, topics, whether it is audio or video, whether it is episodic or serial, its explicit mark and when the latest episode came out.\n\nReturns `{data, meta}`: `data` is a `Podcast` object (the shared schema, the same on every platform). Null means unknown.\n\nIn Spotify's words: `categories` is topics.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/spotify/podcast/ (Markdown: https://socialtap.dev/docs/reference/spotify/podcast/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/spotify/podcast/index.md)",
          "url": "https://socialtap.dev/docs/reference/spotify/podcast/"
        },
        "operationId": "spotify.podcast.get",
        "parameters": [
          {
            "description": "The podcast: its link (open.spotify.com/show/2MAi0BvDc6GTFvKFPXnkCL, also under /intl-de/ and /embed/, with any share parameters), a share link (spotify.link/…), its URI (spotify:show:2MAi0BvDc6GTFvKFPXnkCL) or its 22-character ID.",
            "example": "https://open.spotify.com/show/2MAi0BvDc6GTFvKFPXnkCL",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The podcast: its link (open.spotify.com/show/2MAi0BvDc6GTFvKFPXnkCL, also under /intl-de/ and /embed/, with any share parameters), a share link (spotify.link/…), its URI (spotify:show:2MAi0BvDc6GTFvKFPXnkCL) or its 22-character ID.",
              "examples": [
                "https://open.spotify.com/show/2MAi0BvDc6GTFvKFPXnkCL"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "categories": [
                          "Technology"
                        ],
                        "cover_url": "https://i.scdn.co/image/ab6765630000ba8a563ebb538d297875b10114b7",
                        "description": "Conversations that explore technology, history, philosophy, physics, mathematics, biology, chemistry, engineering, AI, robotics, programming, music, film, art, sports, psychology, neuroscience, geopolitics, business, economics, religion, astronomy, and the human condition with pe…",
                        "id": "2MAi0BvDc6GTFvKFPXnkCL",
                        "is_explicit": null,
                        "latest_episode_at": "2026-10-26T22:57:00Z",
                        "media_type": "mixed",
                        "metrics": {
                          "episode_count": 504,
                          "rating_count": 83249
                        },
                        "platform": "spotify",
                        "platform_specific": {},
                        "publisher": null,
                        "publisher_name": "Lex Fridman",
                        "rating": 4.749810808538215,
                        "show_type": "episodic",
                        "title": "Lex Fridman Podcast",
                        "unknown_fields": [],
                        "url": "https://open.spotify.com/show/2MAi0BvDc6GTFvKFPXnkCL"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "spotify",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 664,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "podcast",
                          "id": "2MAi0BvDc6GTFvKFPXnkCL",
                          "url": "https://open.spotify.com/show/2MAi0BvDc6GTFvKFPXnkCL"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SpotifyPodcastResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact rating, episode count and topics",
        "tags": [
          "Spotify"
        ],
        "x-socialtap-endpoint": "spotify.podcast",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "podcast",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/spotify/podcast_episodes": {
      "get": {
        "description": "Returns the episodes of a public Spotify podcast, a page at a time in the show's own order, from its link, share link, URI or ID. Each has its title, full description, exact release time, length, cover, whether it is audio or video, explicit flag, whether only subscribers hear it in full, and a preview clip. Filter by date with since and until.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Post` items (Spotify calls it a track) (the shared schema, the same on every platform), the show's own order: newest first, or from the first episode on a show meant to be heard in order. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Spotify's words: `metrics.view_count` is plays.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/spotify/podcast_episodes/ (Markdown: https://socialtap.dev/docs/reference/spotify/podcast_episodes/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/spotify/podcast_episodes/index.md)",
          "url": "https://socialtap.dev/docs/reference/spotify/podcast_episodes/"
        },
        "operationId": "spotify.podcast_episodes.list",
        "parameters": [
          {
            "description": "The podcast: its link (open.spotify.com/show/2MAi0BvDc6GTFvKFPXnkCL, also under /intl-de/ and /embed/, with any share parameters), a share link (spotify.link/…), its URI (spotify:show:2MAi0BvDc6GTFvKFPXnkCL) or its 22-character ID.",
            "example": "https://open.spotify.com/show/2MAi0BvDc6GTFvKFPXnkCL",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The podcast: its link (open.spotify.com/show/2MAi0BvDc6GTFvKFPXnkCL, also under /intl-de/ and /embed/, with any share parameters), a share link (spotify.link/…), its URI (spotify:show:2MAi0BvDc6GTFvKFPXnkCL) or its 22-character ID.",
              "examples": [
                "https://open.spotify.com/show/2MAi0BvDc6GTFvKFPXnkCL"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i.scdn.co/image/ab6765630000ba8a563ebb538d297875b10114b7",
                            "display_name": "Lex Fridman Podcast",
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "coauthors": [],
                          "duration_ms": 13327488,
                          "hashtags": [],
                          "id": "0ndqMvnUJkNmQrhK98R09Y",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://i.scdn.co/image/ab6765630000ba8a563ebb538d297875b10114b7",
                              "type": "audio",
                              "url": "https://p.scdn.co/mp3-preview/5a779c504466ba4bce6b571982043964ede1f5c5.mp3",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "added_at": null,
                              "added_by": null,
                              "album_id": null,
                              "album_title": null,
                              "album_track_count": null,
                              "album_type": null,
                              "album_url": null,
                              "bpm": null,
                              "camelot_key": null,
                              "canonical_track_id": null,
                              "copyrights": [],
                              "credits": [],
                              "disc_number": null,
                              "is_explicit": false,
                              "is_paywalled": false,
                              "is_playable": true,
                              "isrc": null,
                              "label": null,
                              "languages": [],
                              "music_video_count": null,
                              "musical_key": null,
                              "playability_reason": "playable",
                              "podcast_id": "2MAi0BvDc6GTFvKFPXnkCL",
                              "popularity": null,
                              "release_date_precision": null,
                              "track_number": null
                            }
                          },
                          "platform_type": "episode",
                          "published_at": "2026-10-26T22:57:00Z",
                          "text": "Ankur Moitra, Steven Brunton and Alex Kontorovich are three mathematicians who can speak to this incredible moment in the history of mathematics, when AI solved some of its hardest problems: Navier-Stokes, the quasi-Riemann hypothesis, the unique games conjecture and hundreds of …",
                          "thumbnail_url": "https://i.scdn.co/image/ab6765630000ba8a563ebb538d297875b10114b7",
                          "title": "#503 – AI Crisis in Math: Navier-Stokes, Riemann Hypothesis & Complexity Theory",
                          "type": "audio",
                          "unknown_fields": [],
                          "url": "https://open.spotify.com/episode/0ndqMvnUJkNmQrhK98R09Y"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i.scdn.co/image/ab6765630000ba8a563ebb538d297875b10114b7",
                            "display_name": "Lex Fridman Podcast",
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "coauthors": [],
                          "duration_ms": 13409643,
                          "hashtags": [],
                          "id": "082a1V6nazH9ZZqskV1vfz",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://i.scdn.co/image/ab6765630000ba8ac0294c0d8ae28ab5e8aa4863",
                              "type": "audio",
                              "url": "https://p.scdn.co/mp3-preview/58e0916ff165341de3cc9bde8c6da49bc8190ec0.mp3",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "added_at": null,
                              "added_by": null,
                              "album_id": null,
                              "album_title": null,
                              "album_track_count": null,
                              "album_type": null,
                              "album_url": null,
                              "bpm": null,
                              "camelot_key": null,
                              "canonical_track_id": null,
                              "copyrights": [],
                              "credits": [],
                              "disc_number": null,
                              "is_explicit": false,
                              "is_paywalled": false,
                              "is_playable": true,
                              "isrc": null,
                              "label": null,
                              "languages": [],
                              "music_video_count": null,
                              "musical_key": null,
                              "playability_reason": "playable",
                              "podcast_id": "2MAi0BvDc6GTFvKFPXnkCL",
                              "popularity": null,
                              "release_date_precision": null,
                              "track_number": null
                            }
                          },
                          "platform_type": "episode",
                          "published_at": "2026-09-17T00:42:00Z",
                          "text": "Andrew Scull is a historian of psychiatry.Thank you for listening ❤ Check out our sponsors: https://lexfridman.com/sponsors/ep502-sdSee below for timestamps, transcript, and to give feedback, submit questions, contact Lex, etc.Transcript:https://lexfridman.com/andrew-scull-transc…",
                          "thumbnail_url": "https://i.scdn.co/image/ab6765630000ba8ac0294c0d8ae28ab5e8aa4863",
                          "title": "#502 – Psychiatry, Insane Asylums, Mental Illness, ECT, Lobotomies, Freud & Jung",
                          "type": "audio",
                          "unknown_fields": [],
                          "url": "https://open.spotify.com/episode/082a1V6nazH9ZZqskV1vfz"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://i.scdn.co/image/ab6765630000ba8a563ebb538d297875b10114b7",
                            "display_name": "Lex Fridman Podcast",
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "coauthors": [],
                          "duration_ms": 19285140,
                          "hashtags": [],
                          "id": "45lhw2Adbrsw0xSCOgIeg3",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://i.scdn.co/image/ab6765630000ba8a00490133143af11512aa2eb9",
                              "type": "audio",
                              "url": "https://p.scdn.co/mp3-preview/4b1be06d8d418d2648bd63d351f252d41120a3bf.mp3",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "added_at": null,
                              "added_by": null,
                              "album_id": null,
                              "album_title": null,
                              "album_track_count": null,
                              "album_type": null,
                              "album_url": null,
                              "bpm": null,
                              "camelot_key": null,
                              "canonical_track_id": null,
                              "copyrights": [],
                              "credits": [],
                              "disc_number": null,
                              "is_explicit": false,
                              "is_paywalled": false,
                              "is_playable": true,
                              "isrc": null,
                              "label": null,
                              "languages": [],
                              "music_video_count": null,
                              "musical_key": null,
                              "playability_reason": "playable",
                              "podcast_id": "2MAi0BvDc6GTFvKFPXnkCL",
                              "popularity": null,
                              "release_date_precision": null,
                              "track_number": null
                            }
                          },
                          "platform_type": "episode",
                          "published_at": "2026-08-26T21:47:00Z",
                          "text": "DHH is the creator of Ruby on Rails, Omarchy Linux, CTO of 37signals, and a racecar driver.Thank you for listening ❤ Check out our sponsors: https://lexfridman.com/sponsors/ep501-sdSee below for timestamps, transcript, and to give feedback, submit questions, contact Lex, etc.Tran…",
                          "thumbnail_url": "https://i.scdn.co/image/ab6765630000ba8a00490133143af11512aa2eb9",
                          "title": "#501 – DHH: Future of Programming, AI, Agentic Engineering, Vibe Coding & Linux",
                          "type": "audio",
                          "unknown_fields": [],
                          "url": "https://open.spotify.com/episode/45lhw2Adbrsw0xSCOgIeg3"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "spotify",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 301,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "podcast",
                          "id": "2MAi0BvDc6GTFvKFPXnkCL",
                          "url": "https://open.spotify.com/show/2MAi0BvDc6GTFvKFPXnkCL"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SpotifyPodcast_episodesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Full descriptions and exact release times",
        "tags": [
          "Spotify"
        ],
        "x-socialtap-endpoint": "spotify.podcast_episodes",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the show's own order: newest first, or from the first episode on a show meant to be heard in order",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/spotify/search_albums": {
      "get": {
        "description": "Searches Spotify albums, singles and EPs by keyword, artist or UPC, in any language, and returns them a page at a time in Spotify's order. Each has its title, type, credited artists with their IDs, cover and release year. Spotify's filters work in the query: upc: finds a release by its barcode and tag:new the newest. The Spotify Album API adds the full date, label, UPC, copyrights and tracks.\n\nReturns `{data, page, meta}`: `data` holds up to 100 `Album` items (the shared schema, the same on every platform), Spotify's own ranking for the query. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Spotify's words: `tracks[].metrics.view_count` is plays.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/spotify/search_albums/ (Markdown: https://socialtap.dev/docs/reference/spotify/search_albums/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/spotify/search_albums/index.md)",
          "url": "https://socialtap.dev/docs/reference/spotify/search_albums/"
        },
        "operationId": "spotify.search_albums.list",
        "parameters": [
          {
            "description": "What to search for, as in Spotify's search box: a title, an artist or both, in any language. Spotify's own filters work too: artist:\"rick astley\" year:1987, year:1987-1988, album:abbey road, upc:886445613841 finds a release by its barcode, tag:new its newest.",
            "example": "rick astley",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to search for, as in Spotify's search box: a title, an artist or both, in any language. Spotify's own filters work too: artist:\"rick astley\" year:1987, year:1987-1988, album:abbey road, upc:886445613841 finds a release by its barcode, tag:new its newest.",
              "examples": [
                "rick astley"
              ],
              "maxLength": 250,
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's names, where Spotify holds a name in several (an artist's name in Japanese or in Latin letters). It can reorder the results a little.",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's names, where Spotify holds a name in several (an artist's name in Japanese or in Latin letters). It can reorder the results a little.",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 100,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "released_at"
                          ],
                          "artist_name": "Rick Astley",
                          "artists": [
                            {
                              "avatar_url": null,
                              "display_name": "Rick Astley",
                              "id": "0gxyHStUsqpMadRV0Di1Qt",
                              "is_verified": null,
                              "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                              "username": null
                            }
                          ],
                          "copyrights": [],
                          "cover_url": "https://i.scdn.co/image/ab67616d0000b27315ebbedaacef61af244262a8",
                          "description": null,
                          "duration_ms": null,
                          "genres": [],
                          "id": "6eUW0wxWtzkFdaEFsTJto6",
                          "is_explicit": null,
                          "label": null,
                          "metrics": {
                            "track_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "is_playable": true,
                              "is_pre_release": false,
                              "popularity": null,
                              "pre_release_ends_at": null,
                              "release_date_precision": "year"
                            }
                          },
                          "released_at": "1987-01-01T00:00:00Z",
                          "title": "Whenever You Need Somebody",
                          "tracks": [],
                          "type": "single",
                          "unknown_fields": [
                            "genres",
                            "copyrights",
                            "tracks"
                          ],
                          "upc": null,
                          "url": "https://open.spotify.com/album/6eUW0wxWtzkFdaEFsTJto6"
                        },
                        {
                          "approximate_fields": [
                            "released_at"
                          ],
                          "artist_name": "Rick Astley",
                          "artists": [
                            {
                              "avatar_url": null,
                              "display_name": "Rick Astley",
                              "id": "0gxyHStUsqpMadRV0Di1Qt",
                              "is_verified": null,
                              "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                              "username": null
                            }
                          ],
                          "copyrights": [],
                          "cover_url": "https://i.scdn.co/image/ab67616d0000b273ad292ed19701d9f5c8cf71b6",
                          "description": null,
                          "duration_ms": null,
                          "genres": [],
                          "id": "6CWdaSQN5rsdDkOrhFcZ0E",
                          "is_explicit": null,
                          "label": null,
                          "metrics": {
                            "track_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "is_playable": true,
                              "is_pre_release": false,
                              "popularity": null,
                              "pre_release_ends_at": null,
                              "release_date_precision": "year"
                            }
                          },
                          "released_at": "2019-01-01T00:00:00Z",
                          "title": "The Best of Me",
                          "tracks": [],
                          "type": "compilation",
                          "unknown_fields": [
                            "genres",
                            "copyrights",
                            "tracks"
                          ],
                          "upc": null,
                          "url": "https://open.spotify.com/album/6CWdaSQN5rsdDkOrhFcZ0E"
                        },
                        {
                          "approximate_fields": [
                            "released_at"
                          ],
                          "artist_name": "Rick Astley",
                          "artists": [
                            {
                              "avatar_url": null,
                              "display_name": "Rick Astley",
                              "id": "0gxyHStUsqpMadRV0Di1Qt",
                              "is_verified": null,
                              "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                              "username": null
                            }
                          ],
                          "copyrights": [],
                          "cover_url": "https://i.scdn.co/image/ab67616d0000b2733a67639779ccabd632e1a80e",
                          "description": null,
                          "duration_ms": null,
                          "genres": [],
                          "id": "4C4LvbYS0pxXLW5sGD9EK5",
                          "is_explicit": null,
                          "label": null,
                          "metrics": {
                            "track_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "is_playable": true,
                              "is_pre_release": false,
                              "popularity": null,
                              "pre_release_ends_at": null,
                              "release_date_precision": "year"
                            }
                          },
                          "released_at": "2022-01-01T00:00:00Z",
                          "title": "Whenever You Need Somebody (Deluxe Edition - 2022 Remaster)",
                          "tracks": [],
                          "type": "album",
                          "unknown_fields": [
                            "genres",
                            "copyrights",
                            "tracks"
                          ],
                          "upc": null,
                          "url": "https://open.spotify.com/album/4C4LvbYS0pxXLW5sGD9EK5"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "spotify",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 687,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SpotifySearch_albumsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Albums by keyword, artist or UPC",
        "tags": [
          "Spotify"
        ],
        "x-socialtap-endpoint": "spotify.search_albums",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Spotify's own ranking for the query",
          "page_max": 100,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "album",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/spotify/search_artists": {
      "get": {
        "description": "Searches Spotify artists by name in any language and returns them a page at a time, each with its Spotify ID, picture and verified badge. Spotify's AI persona label is there too. Set kind=listener for the people, brands and labels that own playlists, with their usernames. The Spotify Artist API adds the bio, followers, monthly listeners, top cities and discography.\n\nReturns `{data, page, meta}`: `data` holds up to 100 `Profile` items (Spotify calls it a artist) (the shared schema, the same on every platform), Spotify's own ranking for the query. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/spotify/search_artists/ (Markdown: https://socialtap.dev/docs/reference/spotify/search_artists/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/spotify/search_artists/index.md)",
          "url": "https://socialtap.dev/docs/reference/spotify/search_artists/"
        },
        "operationId": "spotify.search_artists.list",
        "parameters": [
          {
            "description": "The name to search for, in any language. On artists, Spotify's filters artist:\"rick astley\" (that name closely) and year:1987 work too.",
            "example": "rick astley",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "The name to search for, in any language. On artists, Spotify's filters artist:\"rick astley\" (that name closely) and year:1987 work too.",
              "examples": [
                "rick astley"
              ],
              "maxLength": 250,
              "type": "string"
            }
          },
          {
            "description": "Whose accounts: artist (default), or listener, the people, brands and labels whose accounts own playlists. Spotify's search finds a listener by a close match of the name, among the candidates it reads a hundred at a time, so a page often holds a few accounts and next_cursor has the rest; a list can be empty, and there is no fallback as artists have.",
            "example": "artist",
            "in": "query",
            "name": "kind",
            "schema": {
              "default": "artist",
              "description": "Whose accounts: artist (default), or listener, the people, brands and labels whose accounts own playlists. Spotify's search finds a listener by a close match of the name, among the candidates it reads a hundred at a time, so a page often holds a few accounts and next_cursor has the rest; a list can be empty, and there is no fallback as artists have.",
              "enum": [
                "artist",
                "listener"
              ],
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's names, where Spotify holds a name in several (an artist's name in Japanese or in Latin letters). It can reorder the results a little.",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's names, where Spotify holds a name in several (an artist's name in Japanese or in Latin letters). It can reorder the results a little.",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 100,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://i.scdn.co/image/ab6761610000e5eb854861dff9a24a1ed3dfdc7d",
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "Rick Astley",
                          "external_links": [],
                          "id": "0gxyHStUsqpMadRV0Di1Qt",
                          "is_private": null,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "active_decades": [],
                              "ai_persona": null,
                              "albums": null,
                              "appears_on": null,
                              "biography_type": null,
                              "compilations": null,
                              "concert_count": null,
                              "concerts": [],
                              "discovered_on": [],
                              "discovered_on_count": null,
                              "featured_in": [],
                              "featured_in_count": null,
                              "gallery_urls": [],
                              "is_registered": null,
                              "latest_release": null,
                              "monthly_listener_count": null,
                              "music_video_count": null,
                              "music_videos": [],
                              "pinned_item": null,
                              "playlist_count": null,
                              "playlists": [],
                              "popular_release_count": null,
                              "popular_releases": [],
                              "popularity": null,
                              "related_artist_count": null,
                              "related_artists": [],
                              "singles": null,
                              "top_cities": [],
                              "top_tracks": [],
                              "world_rank": null
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.spotify.active_decades",
                            "platform_specific.spotify.gallery_urls"
                          ],
                          "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                          "username": null
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://i.scdn.co/image/c89848e407aa02ab2ebfe404843812fe16cad5b7",
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "Sheena Easton",
                          "external_links": [],
                          "id": "5dcOK4stT4JDkP6Dqhbz5s",
                          "is_private": null,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "active_decades": [],
                              "ai_persona": null,
                              "albums": null,
                              "appears_on": null,
                              "biography_type": null,
                              "compilations": null,
                              "concert_count": null,
                              "concerts": [],
                              "discovered_on": [],
                              "discovered_on_count": null,
                              "featured_in": [],
                              "featured_in_count": null,
                              "gallery_urls": [],
                              "is_registered": null,
                              "latest_release": null,
                              "monthly_listener_count": null,
                              "music_video_count": null,
                              "music_videos": [],
                              "pinned_item": null,
                              "playlist_count": null,
                              "playlists": [],
                              "popular_release_count": null,
                              "popular_releases": [],
                              "popularity": null,
                              "related_artist_count": null,
                              "related_artists": [],
                              "singles": null,
                              "top_cities": [],
                              "top_tracks": [],
                              "world_rank": null
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.spotify.active_decades",
                            "platform_specific.spotify.gallery_urls"
                          ],
                          "url": "https://open.spotify.com/artist/5dcOK4stT4JDkP6Dqhbz5s",
                          "username": null
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://i.scdn.co/image/ab6761610000e5eb2ebf587c72f9e5159da9ce55",
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "Wham!",
                          "external_links": [],
                          "id": "5lpH0xAS4fVfLkACg9DAuM",
                          "is_private": null,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "active_decades": [],
                              "ai_persona": null,
                              "albums": null,
                              "appears_on": null,
                              "biography_type": null,
                              "compilations": null,
                              "concert_count": null,
                              "concerts": [],
                              "discovered_on": [],
                              "discovered_on_count": null,
                              "featured_in": [],
                              "featured_in_count": null,
                              "gallery_urls": [],
                              "is_registered": null,
                              "latest_release": null,
                              "monthly_listener_count": null,
                              "music_video_count": null,
                              "music_videos": [],
                              "pinned_item": null,
                              "playlist_count": null,
                              "playlists": [],
                              "popular_release_count": null,
                              "popular_releases": [],
                              "popularity": null,
                              "related_artist_count": null,
                              "related_artists": [],
                              "singles": null,
                              "top_cities": [],
                              "top_tracks": [],
                              "world_rank": null
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.spotify.active_decades",
                            "platform_specific.spotify.gallery_urls"
                          ],
                          "url": "https://open.spotify.com/artist/5lpH0xAS4fVfLkACg9DAuM",
                          "username": null
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "spotify",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 814,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SpotifySearch_artistsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Artists and listener accounts by name",
        "tags": [
          "Spotify"
        ],
        "x-socialtap-endpoint": "spotify.search_artists",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Spotify's own ranking for the query",
          "page_max": 100,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/spotify/search_playlists": {
      "get": {
        "description": "Searches Spotify's public playlists by keyword in any language and returns them a page at a time, in Spotify's order. Each has its title, description, cover, owner with their username and picture, the kind of list Spotify says it is, and whether its algorithm made it. The Spotify Playlist API adds the follower count, item count and dates.\n\nReturns `{data, page, meta}`: `data` holds up to 100 `Playlist` items (the shared schema, the same on every platform), Spotify's own ranking for the query. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/spotify/search_playlists/ (Markdown: https://socialtap.dev/docs/reference/spotify/search_playlists/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/spotify/search_playlists/index.md)",
          "url": "https://socialtap.dev/docs/reference/spotify/search_playlists/"
        },
        "operationId": "spotify.search_playlists.list",
        "parameters": [
          {
            "description": "What to search for, as in Spotify's search box: a playlist's title, a mood, a genre or an artist, in any language. Spotify's filters for music (artist:, album:, track:, year:, genre:, label:, isrc:, upc:, tag:) match no playlist and answer an empty page, alone or beside other words.",
            "example": "workout",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to search for, as in Spotify's search box: a playlist's title, a mood, a genre or an artist, in any language. Spotify's filters for music (artist:, album:, track:, year:, genre:, label:, isrc:, upc:, tag:) match no playlist and answer an empty page, alone or beside other words.",
              "examples": [
                "workout"
              ],
              "maxLength": 250,
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's titles and descriptions, where Spotify holds them in several, as on its own lists (Dance Pop Mix, ダンス・ポップMix). A listener's playlist stays as they wrote it. It can reorder the results a little.",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's titles and descriptions, where Spotify holds them in several, as on its own lists (Dance Pop Mix, ダンス・ポップMix). A listener's playlist stays as they wrote it. It can reorder the results a little.",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 100,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "description": "Bangers Workout music for you. Also try rap, latin, reggaeton, dance, exotica",
                          "id": "37i9dQZF1EIeNbDmYrgnbS",
                          "is_collaborative": null,
                          "metrics": {
                            "post_count": null
                          },
                          "owner": {
                            "avatar_url": "https://i.scdn.co/image/ab6775700000ee8555c25988a6ac314394d3fbf5",
                            "display_name": "Spotify",
                            "id": null,
                            "is_verified": null,
                            "url": "https://open.spotify.com/user/spotify",
                            "username": "spotify"
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "created_at": null,
                              "follower_count": null,
                              "is_algorithmic": null,
                              "is_collaborative": null,
                              "is_deleted_by_owner": null,
                              "is_user_created": null,
                              "updated_at": null
                            }
                          },
                          "platform_type": "descripto",
                          "thumbnail_url": "https://seed-mix-image.spotifycdn.com/v6/img/desc/Bangers%20Workout/en/default",
                          "title": "Bangers Workout Mix",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://open.spotify.com/playlist/37i9dQZF1EIeNbDmYrgnbS"
                        },
                        {
                          "approximate_fields": [],
                          "description": null,
                          "id": "2rKxqZEf3zcoateybTiJDn",
                          "is_collaborative": null,
                          "metrics": {
                            "post_count": null
                          },
                          "owner": {
                            "avatar_url": "https://i.scdn.co/image/ab6775700000ee859e5e623e05ef20c32dc9d8bc",
                            "display_name": "PureWow",
                            "id": null,
                            "is_verified": null,
                            "url": "https://open.spotify.com/user/purewow",
                            "username": "purewow"
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "created_at": null,
                              "follower_count": null,
                              "is_algorithmic": null,
                              "is_collaborative": null,
                              "is_deleted_by_owner": null,
                              "is_user_created": null,
                              "updated_at": null
                            }
                          },
                          "platform_type": "playlist",
                          "thumbnail_url": "https://mosaic.scdn.co/640/ab67616d00001e0282db43e5091301205076d6abab67616d00001e02926f43e7cce571e62720fd46ab67616d00001e02b52264e58d9bb36257770a89ab67616d00001e02f9f27162ab1ed45b8d7a7e98",
                          "title": "50 Best Workout Songs That Will Have You *Actually* Breaking a Sweat",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://open.spotify.com/playlist/2rKxqZEf3zcoateybTiJDn"
                        },
                        {
                          "approximate_fields": [],
                          "description": "LOCK IN LADIES!!!  💪🏼💸💖🧘🏻‍♀️ Revenge Body So He Regrets It, Hot Girl Walk, Hot Girls Lift Weights, Fitness Girlies, Yoga, Running, Pilates, Treadmill, Cardio, Bad Bitch Workout Playlist, Hot Gym Girls, Hot Girl Workout, BEST GYM SONGS HYPE",
                          "id": "0OxRbscW9gq3FzENFlUPes",
                          "is_collaborative": null,
                          "metrics": {
                            "post_count": null
                          },
                          "owner": {
                            "avatar_url": "https://i.scdn.co/image/ab6775700000ee850afa00fab7ae8a4c76278e1a",
                            "display_name": "BAD KITTY 😈",
                            "id": null,
                            "is_verified": null,
                            "url": "https://open.spotify.com/user/lqz5moj5fvn3k4mrdg9ewu0g1",
                            "username": "lqz5moj5fvn3k4mrdg9ewu0g1"
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "created_at": null,
                              "follower_count": null,
                              "is_algorithmic": null,
                              "is_collaborative": null,
                              "is_deleted_by_owner": null,
                              "is_user_created": null,
                              "updated_at": null
                            }
                          },
                          "platform_type": "playlist",
                          "thumbnail_url": "https://image-cdn-fa.spotifycdn.com/image/ab67706c0000da847168a8140b4499c5b1322dbd",
                          "title": "HOT GIRL GYM PLAYLIST 🎀🏋🏻‍♀️ Girly Gym Pump, Workout Songs 2026, Beast Mode Baddie Gym Music",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://open.spotify.com/playlist/0OxRbscW9gq3FzENFlUPes"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "spotify",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 966,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SpotifySearch_playlistsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Playlists and their curators by keyword",
        "tags": [
          "Spotify"
        ],
        "x-socialtap-endpoint": "spotify.search_playlists",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Spotify's own ranking for the query",
          "page_max": 100,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "playlist",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/spotify/search_podcasts": {
      "get": {
        "description": "Searches Spotify podcasts by keyword in any language and returns them a page at a time, in Spotify's order. Each has its ID, link, name, publisher, largest cover, whether its episodes are audio or video, and its categories. The Spotify Podcast API adds the description, rating, episode count and latest episode's date.\n\nReturns `{data, page, meta}`: `data` holds up to 100 `Podcast` items (the shared schema, the same on every platform), Spotify's own ranking for the query. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Spotify's words: `categories` is topics.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/spotify/search_podcasts/ (Markdown: https://socialtap.dev/docs/reference/spotify/search_podcasts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/spotify/search_podcasts/index.md)",
          "url": "https://socialtap.dev/docs/reference/spotify/search_podcasts/"
        },
        "operationId": "spotify.search_podcasts.list",
        "parameters": [
          {
            "description": "What to search for, as in Spotify's search box: a show's name, who publishes it or a topic, in any language. Spotify's filters for music (artist:, album:, year:, genre:, track:, tag:, isrc:) match no podcast, alone or beside other words, and answer an empty page.",
            "example": "true crime",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to search for, as in Spotify's search box: a show's name, who publishes it or a topic, in any language. Spotify's filters for music (artist:, album:, year:, genre:, track:, tag:, isrc:) match no podcast, alone or beside other words, and answer an empty page.",
              "examples": [
                "true crime"
              ],
              "maxLength": 250,
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's categories, where Spotify holds them in several (True crime, 言語). It can reorder the results a little.",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's categories, where Spotify holds them in several (True crime, 言語). It can reorder the results a little.",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 100,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "categories": [
                            "True crime"
                          ],
                          "cover_url": "https://i.scdn.co/image/ab6765630000ba8abe2cc3efd92b817b54d9bcb2",
                          "description": null,
                          "id": "3DgfoleqaW61T2amZQKINx",
                          "is_explicit": null,
                          "latest_episode_at": null,
                          "media_type": "audio",
                          "metrics": {
                            "episode_count": null,
                            "rating_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {},
                          "publisher": null,
                          "publisher_name": "Audiochuck",
                          "rating": null,
                          "show_type": null,
                          "title": "Crime Junkie",
                          "unknown_fields": [],
                          "url": "https://open.spotify.com/show/3DgfoleqaW61T2amZQKINx"
                        },
                        {
                          "approximate_fields": [],
                          "categories": [
                            "True crime"
                          ],
                          "cover_url": "https://i.scdn.co/image/ab6765630000ba8a6f26a1be3d27a21d83e7cd2f",
                          "description": null,
                          "id": "48GaWhr2cdtOGjF3dF9rLy",
                          "is_explicit": null,
                          "latest_episode_at": null,
                          "media_type": "mixed",
                          "metrics": {
                            "episode_count": null,
                            "rating_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {},
                          "publisher": null,
                          "publisher_name": "True Crime Stories",
                          "rating": null,
                          "show_type": null,
                          "title": "True Crime Stories",
                          "unknown_fields": [],
                          "url": "https://open.spotify.com/show/48GaWhr2cdtOGjF3dF9rLy"
                        },
                        {
                          "approximate_fields": [],
                          "categories": [
                            "True crime"
                          ],
                          "cover_url": "https://i.scdn.co/image/ab6765630000ba8a92b95c1495e411e3fb99659b",
                          "description": null,
                          "id": "2gknS4WovSnrJupP8BVKNe",
                          "is_explicit": null,
                          "latest_episode_at": null,
                          "media_type": "audio",
                          "metrics": {
                            "episode_count": null,
                            "rating_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {},
                          "publisher": null,
                          "publisher_name": "Crime House",
                          "rating": null,
                          "show_type": null,
                          "title": "Serial Killers & Murderous Minds",
                          "unknown_fields": [],
                          "url": "https://open.spotify.com/show/2gknS4WovSnrJupP8BVKNe"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "spotify",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 627,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SpotifySearch_podcastsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Podcasts by keyword, publisher or topic",
        "tags": [
          "Spotify"
        ],
        "x-socialtap-endpoint": "spotify.search_podcasts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Spotify's own ranking for the query",
          "page_max": 100,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "podcast",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/spotify/search_tracks": {
      "get": {
        "description": "Searches Spotify tracks by keyword, artist or ISRC, in any language, and returns them a page at a time in Spotify's order. Each has its title, credited artists with their IDs, album, exact length, cover, explicit flag, music video count and a preview clip. Set kind=episode to search podcast episodes instead. The Spotify Track API adds plays, release date, ISRC, label and credits.\n\nReturns `{data, page, meta}`: `data` holds up to 100 `Post` items (Spotify calls it a track) (the shared schema, the same on every platform), Spotify's own ranking for the query. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Spotify's words: `metrics.view_count` is plays.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/spotify/search_tracks/ (Markdown: https://socialtap.dev/docs/reference/spotify/search_tracks/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/spotify/search_tracks/index.md)",
          "url": "https://socialtap.dev/docs/reference/spotify/search_tracks/"
        },
        "operationId": "spotify.search_tracks.list",
        "parameters": [
          {
            "description": "What to search for, as in Spotify's search box: a title, an artist or both, in any language. Spotify's own filters work too: artist:\"rick astley\" year:1987, track:lemon, album:, genre:, and isrc:GBARL9300135 finds a recording by its code.",
            "example": "rick astley",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "What to search for, as in Spotify's search box: a title, an artist or both, in any language. Spotify's own filters work too: artist:\"rick astley\" year:1987, track:lemon, album:, genre:, and isrc:GBARL9300135 finds a recording by its code.",
              "examples": [
                "rick astley"
              ],
              "maxLength": 250,
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's names, where Spotify holds a name in several (an artist's name in Japanese or in Latin letters). It can reorder the results a little.",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). The language of the answer's names, where Spotify holds a name in several (an artist's name in Japanese or in Latin letters). It can reorder the results a little.",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "What to list: tracks (the default) or podcast episodes. Both come back in the same post shape, and platform_type says which it is.",
            "example": "track",
            "in": "query",
            "name": "kind",
            "schema": {
              "default": "track",
              "description": "What to list: tracks (the default) or podcast episodes. Both come back in the same post shape, and platform_type says which it is.",
              "enum": [
                "track",
                "episode"
              ],
              "examples": [
                "episode"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 100,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": null,
                            "display_name": "Rick Astley",
                            "id": "0gxyHStUsqpMadRV0Di1Qt",
                            "is_verified": null,
                            "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                            "username": null
                          },
                          "coauthors": [],
                          "duration_ms": 213573,
                          "hashtags": [],
                          "id": "4PTG3Z6ehGkBFwjybzWkR8",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://i.scdn.co/image/ab67616d0000b27315ebbedaacef61af244262a8",
                              "type": "audio",
                              "url": "https://p.scdn.co/mp3-preview/b4c682084c3fd05538726d0a126b7e14b6e92c83",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "added_at": null,
                              "added_by": null,
                              "album_id": "6eUW0wxWtzkFdaEFsTJto6",
                              "album_title": "Whenever You Need Somebody",
                              "album_track_count": null,
                              "album_type": null,
                              "album_url": "https://open.spotify.com/album/6eUW0wxWtzkFdaEFsTJto6",
                              "bpm": null,
                              "camelot_key": null,
                              "canonical_track_id": null,
                              "copyrights": [],
                              "credits": [],
                              "disc_number": null,
                              "is_explicit": false,
                              "is_paywalled": null,
                              "is_playable": true,
                              "isrc": null,
                              "label": null,
                              "languages": [],
                              "music_video_count": 1,
                              "musical_key": null,
                              "playability_reason": "playable",
                              "podcast_id": null,
                              "popularity": null,
                              "release_date_precision": null,
                              "track_number": null
                            }
                          },
                          "platform_type": "track",
                          "published_at": null,
                          "text": null,
                          "thumbnail_url": "https://i.scdn.co/image/ab67616d0000b27315ebbedaacef61af244262a8",
                          "title": "Never Gonna Give You Up",
                          "type": "audio",
                          "unknown_fields": [
                            "platform_specific.spotify.copyrights",
                            "platform_specific.spotify.credits",
                            "platform_specific.spotify.languages"
                          ],
                          "url": "https://open.spotify.com/track/4PTG3Z6ehGkBFwjybzWkR8"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": null,
                            "display_name": "Rick Astley",
                            "id": "0gxyHStUsqpMadRV0Di1Qt",
                            "is_verified": null,
                            "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                            "username": null
                          },
                          "coauthors": [],
                          "duration_ms": 205533,
                          "hashtags": [],
                          "id": "00isIFJWVpXIQ8HkGICSQp",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://i.scdn.co/image/ab67616d0000b27315ebbedaacef61af244262a8",
                              "type": "audio",
                              "url": "https://p.scdn.co/mp3-preview/218ce9bda2e7ad945f675c8f3cb48cd94b8718fa",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "added_at": null,
                              "added_by": null,
                              "album_id": "6eUW0wxWtzkFdaEFsTJto6",
                              "album_title": "Whenever You Need Somebody",
                              "album_track_count": null,
                              "album_type": null,
                              "album_url": "https://open.spotify.com/album/6eUW0wxWtzkFdaEFsTJto6",
                              "bpm": null,
                              "camelot_key": null,
                              "canonical_track_id": null,
                              "copyrights": [],
                              "credits": [],
                              "disc_number": null,
                              "is_explicit": false,
                              "is_paywalled": null,
                              "is_playable": true,
                              "isrc": null,
                              "label": null,
                              "languages": [],
                              "music_video_count": 1,
                              "musical_key": null,
                              "playability_reason": "playable",
                              "podcast_id": null,
                              "popularity": null,
                              "release_date_precision": null,
                              "track_number": null
                            }
                          },
                          "platform_type": "track",
                          "published_at": null,
                          "text": null,
                          "thumbnail_url": "https://i.scdn.co/image/ab67616d0000b27315ebbedaacef61af244262a8",
                          "title": "Together Forever",
                          "type": "audio",
                          "unknown_fields": [
                            "platform_specific.spotify.copyrights",
                            "platform_specific.spotify.credits",
                            "platform_specific.spotify.languages"
                          ],
                          "url": "https://open.spotify.com/track/00isIFJWVpXIQ8HkGICSQp"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": null,
                            "display_name": "Rick Astley",
                            "id": "0gxyHStUsqpMadRV0Di1Qt",
                            "is_verified": null,
                            "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                            "username": null
                          },
                          "coauthors": [],
                          "duration_ms": 213560,
                          "hashtags": [],
                          "id": "0yNttAVwMr39qyODHNIkrY",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": "https://i.scdn.co/image/ab67616d0000b2733a67639779ccabd632e1a80e",
                              "type": "audio",
                              "url": "https://p.scdn.co/mp3-preview/40a780b231e5ed130483bec7917b6c9a4f8a4708",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "spotify",
                          "platform_specific": {
                            "spotify": {
                              "added_at": null,
                              "added_by": null,
                              "album_id": "4C4LvbYS0pxXLW5sGD9EK5",
                              "album_title": "Whenever You Need Somebody (Deluxe Edition - 2022 Remaster)",
                              "album_track_count": null,
                              "album_type": null,
                              "album_url": "https://open.spotify.com/album/4C4LvbYS0pxXLW5sGD9EK5",
                              "bpm": null,
                              "camelot_key": null,
                              "canonical_track_id": null,
                              "copyrights": [],
                              "credits": [],
                              "disc_number": null,
                              "is_explicit": false,
                              "is_paywalled": null,
                              "is_playable": true,
                              "isrc": null,
                              "label": null,
                              "languages": [],
                              "music_video_count": 1,
                              "musical_key": null,
                              "playability_reason": "playable",
                              "podcast_id": null,
                              "popularity": null,
                              "release_date_precision": null,
                              "track_number": null
                            }
                          },
                          "platform_type": "track",
                          "published_at": null,
                          "text": null,
                          "thumbnail_url": "https://i.scdn.co/image/ab67616d0000b2733a67639779ccabd632e1a80e",
                          "title": "Never Gonna Give You Up - 2022 Remaster",
                          "type": "audio",
                          "unknown_fields": [
                            "platform_specific.spotify.copyrights",
                            "platform_specific.spotify.credits",
                            "platform_specific.spotify.languages"
                          ],
                          "url": "https://open.spotify.com/track/0yNttAVwMr39qyODHNIkrY"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "spotify",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 816,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SpotifySearch_tracksResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Tracks by keyword, artist or ISRC",
        "tags": [
          "Spotify"
        ],
        "x-socialtap-endpoint": "spotify.search_tracks",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Spotify's own ranking for the query",
          "page_max": 100,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/spotify/track": {
      "get": {
        "description": "Returns a public Spotify track from its link, share link, URI or ID, with its exact play count, ISRC, label and songwriter and producer credits. It also has the artists, album, release date, length, cover, performance languages, popularity score, explicit flag and a preview clip. A podcast episode's link returns that episode.\n\nReturns `{data, meta}`: `data` is a `Post` object (Spotify calls it a track) (the shared schema, the same on every platform). Null means unknown.\n\nIn Spotify's words: `metrics.view_count` is plays.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/spotify/track/ (Markdown: https://socialtap.dev/docs/reference/spotify/track/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/spotify/track/index.md)",
          "url": "https://socialtap.dev/docs/reference/spotify/track/"
        },
        "operationId": "spotify.track.get",
        "parameters": [
          {
            "description": "The track or podcast episode: its link (open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC or open.spotify.com/episode/0ndqMvnUJkNmQrhK98R09Y, also under /intl-de/ and /embed/, with any share parameters, or an album's link with ?highlight=spotify:track:…), a share link (spotify.link/…), its URI (spotify:track:4uLU6hMCjMI75M1A2tKUQC, spotify:episode:0ndqMvnUJkNmQrhK98R09Y) or its 22-character ID.",
            "example": "https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The track or podcast episode: its link (open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC or open.spotify.com/episode/0ndqMvnUJkNmQrhK98R09Y, also under /intl-de/ and /embed/, with any share parameters, or an album's link with ?highlight=spotify:track:…), a share link (spotify.link/…), its URI (spotify:track:4uLU6hMCjMI75M1A2tKUQC, spotify:episode:0ndqMvnUJkNmQrhK98R09Y) or its 22-character ID.",
              "examples": [
                "https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "published_at"
                        ],
                        "author": {
                          "avatar_url": "https://i.scdn.co/image/ab6761610000e5eb854861dff9a24a1ed3dfdc7d",
                          "display_name": "Rick Astley",
                          "id": "0gxyHStUsqpMadRV0Di1Qt",
                          "is_verified": null,
                          "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt",
                          "username": null
                        },
                        "coauthors": [],
                        "duration_ms": 213573,
                        "hashtags": [],
                        "id": "4uLU6hMCjMI75M1A2tKUQC",
                        "is_nsfw": null,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": null,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": null,
                            "expires_at": null,
                            "height": null,
                            "thumbnail_url": "https://i.scdn.co/image/ab67616d0000b273255e131abc1410833be95673",
                            "type": "audio",
                            "url": "https://p.scdn.co/mp3-preview/40a780b231e5ed130483bec7917b6c9a4f8a4708",
                            "width": null
                          }
                        ],
                        "mentions": [],
                        "metrics": {
                          "comment_count": null,
                          "like_count": null,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": null,
                          "share_count": null,
                          "view_count": 1200207819
                        },
                        "platform": "spotify",
                        "platform_specific": {
                          "spotify": {
                            "added_at": null,
                            "added_by": null,
                            "album_id": "6N9PS4QXF1D0OWPk0Sxtb4",
                            "album_title": "Whenever You Need Somebody",
                            "album_track_count": 10,
                            "album_type": "album",
                            "album_url": "https://open.spotify.com/album/6N9PS4QXF1D0OWPk0Sxtb4",
                            "bpm": null,
                            "camelot_key": null,
                            "canonical_track_id": "0yNttAVwMr39qyODHNIkrY",
                            "copyrights": [
                              {
                                "text": "(P) 1987 Sony Music Entertainment UK Limited under exclusive license to BMG Rights Management (UK) Limited",
                                "type": "p"
                              }
                            ],
                            "credits": [
                              {
                                "artist_id": "0gxyHStUsqpMadRV0Di1Qt",
                                "group": "Artist",
                                "name": "Rick Astley",
                                "role": "Main Artist"
                              },
                              {
                                "artist_id": "2JhG3QOWCDbDXNYhqFDSj1",
                                "group": "Composition & Lyrics",
                                "name": "Mike Stock",
                                "role": "Composer"
                              },
                              {
                                "artist_id": "2JhG3QOWCDbDXNYhqFDSj1",
                                "group": "Composition & Lyrics",
                                "name": "Mike Stock",
                                "role": "Lyricist"
                              }
                            ],
                            "disc_number": 1,
                            "is_explicit": false,
                            "is_paywalled": null,
                            "is_playable": true,
                            "isrc": "GBARL9300135",
                            "label": "Sony Music CG",
                            "languages": [
                              "en"
                            ],
                            "music_video_count": 1,
                            "musical_key": null,
                            "playability_reason": "playable",
                            "podcast_id": null,
                            "popularity": 5,
                            "release_date_precision": "day",
                            "track_number": 1
                          }
                        },
                        "platform_type": "track",
                        "published_at": "1987-11-12T00:00:00Z",
                        "text": null,
                        "thumbnail_url": "https://i.scdn.co/image/ab67616d0000b273255e131abc1410833be95673",
                        "title": "Never Gonna Give You Up",
                        "type": "audio",
                        "unknown_fields": [],
                        "url": "https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "spotify",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 472,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "4uLU6hMCjMI75M1A2tKUQC",
                          "url": "https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SpotifyTrackResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Song with exact plays, ISRC and songwriter credits",
        "tags": [
          "Spotify"
        ],
        "x-socialtap-endpoint": "spotify.track",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/telegram/channel": {
      "get": {
        "description": "Returns a public Telegram channel, group, user or bot from its username or link, with its subscriber or member count, name, bio and photo. It also has the links in its bio, verified badge, members online in a group, a bot's monthly users, and which kind of account it is. A channel also has its creation date, numeric ID, and how many photos, videos, links and files it has posted.\n\nReturns `{data, meta}`: `data` is a `Profile` object (Telegram calls it a channel) (the shared schema, the same on every platform). Null means unknown.\n\nIn Telegram's words: `metrics.follower_count` is subscribers.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/telegram/channel/ (Markdown: https://socialtap.dev/docs/reference/telegram/channel/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/telegram/channel/index.md)",
          "url": "https://socialtap.dev/docs/reference/telegram/channel/"
        },
        "operationId": "telegram.channel.get",
        "parameters": [
          {
            "description": "The Telegram channel, group, user or bot: its username with or without the @, or any link to it (t.me/durov, t.me/s/durov, telegram.me/durov, durov.t.me).",
            "example": "durov",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Telegram channel, group, user or bot: its username with or without the @, or any link to it (t.me/durov, t.me/s/durov, telegram.me/durov, durov.t.me).",
              "examples": [
                "durov"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://cdn4.telesco.pe/file/j6dxnmHRzV_4Tn0IpvsZNLgcbbdsGKZp99CxelC0VTSrxrYs-jbwXpAV5gNt8MxD5Cy9LTEM5_avh9_j_6plyq2J41XnT8fJYBI8kx7r0gHGj42RyZwJUqjd4Ikyv0qB5zFDfcIYAzokGoFuE7WTQ5Lbkfnx7HOZL-Sw5bHEMXPCQToujfyCuku9LCwiunkhLNdZ63DiBhJjl2ucypG5ki66yS0ltfdAzEQEdZoi9jEgpnGVzxHvCfkG5oX…",
                        "banner_url": null,
                        "bio": "Founder of Telegram.",
                        "category": null,
                        "country_code": null,
                        "created_at": "2015-10-28T18:20:58Z",
                        "display_name": "Pavel Durov",
                        "external_links": [],
                        "id": "durov",
                        "is_private": false,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 10127043,
                          "following_count": null,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "telegram",
                        "platform_specific": {
                          "telegram": {
                            "account_type": "channel",
                            "channel_id": "1006503122",
                            "file_count": null,
                            "is_preview_available": true,
                            "link_count": 200,
                            "monthly_user_count": null,
                            "online_count": null,
                            "photo_count": 102,
                            "video_count": 47
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://t.me/durov",
                        "username": "durov"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "telegram",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 701,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "durov",
                          "url": "https://t.me/durov"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TelegramChannelResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Subscribers, bio and links of channels and groups",
        "tags": [
          "Telegram"
        ],
        "x-socialtap-endpoint": "telegram.channel",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/telegram/channel_posts": {
      "get": {
        "description": "Returns a public Telegram channel's posts a page at a time, newest first, back to its first post, from its username or link. Each post has its text, the links, hashtags and mentions in it, its date, photos, albums, videos, voice messages and stickers with their files, views, each reaction with its count, its poll, link preview and file, what it was forwarded from or replies to, and whether it was edited. Add contains to search the channel's posts.\n\nReturns `{data, page, meta}`: `data` holds up to 20 `Post` items (the shared schema, the same on every platform), newest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\nIn Telegram's words: `metrics.like_count` is reactions.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/telegram/channel_posts/ (Markdown: https://socialtap.dev/docs/reference/telegram/channel_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/telegram/channel_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/telegram/channel_posts/"
        },
        "operationId": "telegram.channel_posts.list",
        "parameters": [
          {
            "description": "The Telegram channel: its username with or without the @, or any link to it (t.me/durov, t.me/s/durov, telegram.me/durov, durov.t.me).",
            "example": "durov",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Telegram channel: its username with or without the @, or any link to it (t.me/durov, t.me/s/durov, telegram.me/durov, durov.t.me).",
              "examples": [
                "durov"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only the channel's posts matching these words, as the search box of its page reads them (a word, a #hashtag). Telegram's search answers only its newest matches, a little over one page, and can't reach older ones: the walk then ends with page.end_reason platform_limit. Without it, all of its posts.",
            "example": "telegram",
            "in": "query",
            "name": "contains",
            "schema": {
              "description": "Only the channel's posts matching these words, as the search box of its page reads them (a word, a #hashtag). Telegram's search answers only its newest matches, a little over one page, and can't reach older ones: the walk then ends with page.end_reason platform_limit. Without it, all of its posts.",
              "examples": [
                "telegram"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). The walk starts from the newest post, so a window far in the past takes many pages.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). The walk starts from the newest post, so a window far in the past takes many pages.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 20,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count",
                            "platform_specific.telegram.reactions[].count"
                          ],
                          "author": {
                            "avatar_url": "https://cdn4.telesco.pe/file/AM3EaKY4OWoCIpqIJGL2G4hcjBupbm4OuzSyAnEGF2gBOPJJIYOcnXbjDpqmilOWXXjheFFey4oGODL1BybYTdbTaJHo9qb3KEAIw9y3VvSrrKwoRdfBHWovcRqFmFEu5EeKeGrOZPTVcZEHBP6rbBp5qM4WbNdvEbGQLAnCPle0ArPYn70dJpY8D3zpJWbhZ2V1bnF2k0VXfyWUnokwHk6Q56QkaNg5gs1PhbGSaPshnBDj1xw7QOhLE-o…",
                            "display_name": "Pavel Durov",
                            "id": "durov",
                            "is_verified": true,
                            "url": "https://t.me/durov",
                            "username": "durov"
                          },
                          "coauthors": [],
                          "duration_ms": 75000,
                          "hashtags": [],
                          "id": "durov/552",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 75000,
                              "expires_at": null,
                              "height": 1080,
                              "thumbnail_url": "https://cdn4.telesco.pe/file/Q3tIE6CCufCsd8whuPWLILOUHrqgPVUSee0ASTob_qQHilv5bbvW-9Ne_OsQOIeGtqauW7rC9022y_XhCzxKSbX-2gRlYhtYjrOhKGNw9ir-ZPS2ViPvR4SHRzrvxu5wQEcBeTxwpdmOkm5q6_ydiAs1QQY9vZn0YVwi68dQQp6ZYQyFdda9hvcC0pvv9QX9me6Tkb9zrRVpHGP_zO8US4gXDH3QkgZ3_ho7wFFmLEg5CNdurkthtJPHUA7…",
                              "type": "video",
                              "url": null,
                              "width": 1080
                            }
                          ],
                          "mentions": [
                            "designers"
                          ],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 42630,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 1970000
                          },
                          "platform": "telegram",
                          "platform_specific": {
                            "telegram": {
                              "buttons": [],
                              "channel_id": "1006503122",
                              "document": null,
                              "forwarded_from": {
                                "author": null,
                                "name": null,
                                "post_id": null,
                                "url": null
                              },
                              "is_edited": false,
                              "link_preview": null,
                              "links": [
                                "https://t.me/designers"
                              ],
                              "message_id": 552,
                              "poll": null,
                              "reactions": [
                                {
                                  "count": 10400,
                                  "custom_emoji_id": null,
                                  "emoji": null,
                                  "is_paid": true
                                },
                                {
                                  "count": 18300,
                                  "custom_emoji_id": "5936157098181135162",
                                  "emoji": null,
                                  "is_paid": false
                                },
                                {
                                  "count": 7830,
                                  "custom_emoji_id": "5399847211989246390",
                                  "emoji": null,
                                  "is_paid": false
                                }
                              ],
                              "reply_to": null,
                              "sender_name": null,
                              "signature": "Pavel Durov"
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-11T14:52:40Z",
                          "text": "✨ Designers × AI\n\n🆕 The mockup era is over. Today’s AI tools give every designer a superpower: you can now craft your ideas, not just draw them. \n\nThe gap between “what if…?” and “look, it works!” has never been smaller, and that changed how we build features in Telegram.\n\nMessag…",
                          "thumbnail_url": "https://cdn4.telesco.pe/file/Q3tIE6CCufCsd8whuPWLILOUHrqgPVUSee0ASTob_qQHilv5bbvW-9Ne_OsQOIeGtqauW7rC9022y_XhCzxKSbX-2gRlYhtYjrOhKGNw9ir-ZPS2ViPvR4SHRzrvxu5wQEcBeTxwpdmOkm5q6_ydiAs1QQY9vZn0YVwi68dQQp6ZYQyFdda9hvcC0pvv9QX9me6Tkb9zrRVpHGP_zO8US4gXDH3QkgZ3_ho7wFFmLEg5CNdurkthtJPHUA7…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://t.me/durov/552"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count",
                            "platform_specific.telegram.reactions[].count"
                          ],
                          "author": {
                            "avatar_url": "https://cdn4.telesco.pe/file/AM3EaKY4OWoCIpqIJGL2G4hcjBupbm4OuzSyAnEGF2gBOPJJIYOcnXbjDpqmilOWXXjheFFey4oGODL1BybYTdbTaJHo9qb3KEAIw9y3VvSrrKwoRdfBHWovcRqFmFEu5EeKeGrOZPTVcZEHBP6rbBp5qM4WbNdvEbGQLAnCPle0ArPYn70dJpY8D3zpJWbhZ2V1bnF2k0VXfyWUnokwHk6Q56QkaNg5gs1PhbGSaPshnBDj1xw7QOhLE-o…",
                            "display_name": "Pavel Durov",
                            "id": "durov",
                            "is_verified": true,
                            "url": "https://t.me/durov",
                            "username": "durov"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "durov/551",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 1920,
                              "thumbnail_url": "https://cdn4.telesco.pe/file/ef2H_OWJLC-8LfDhQZQeyxdbbsqG5TdelWDugA19pQHkmAfgw_D3-7J6IVVDA2fKbPalVY8lO-7r1ZNdvtTWuzX-eIsqZGQOsgzJ6lFD4e23w4ItpaCcpzoLbzh-kiCktnhnqxq1rR2Ul7qSEwa1NDz5byYymI8W_b9JsNkBkrlVreXDBWU2l9wLQ3iKOYB2VulCHtP-2o-iDaYCTe7jKnLIBmKQICXKPOvdBwIWIMLGvG0VEnsXeYK_oZv…",
                              "type": "gif",
                              "url": "https://cdn4.telesco.pe/file/f4b10a0c75.mp4?token=SCRUBBED",
                              "width": 1920
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 121700,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 2070000
                          },
                          "platform": "telegram",
                          "platform_specific": {
                            "telegram": {
                              "buttons": [],
                              "channel_id": "1006503122",
                              "document": null,
                              "forwarded_from": null,
                              "is_edited": false,
                              "link_preview": null,
                              "links": [],
                              "message_id": 551,
                              "poll": null,
                              "reactions": [
                                {
                                  "count": 60300,
                                  "custom_emoji_id": null,
                                  "emoji": null,
                                  "is_paid": true
                                },
                                {
                                  "count": 38400,
                                  "custom_emoji_id": "5936157098181135162",
                                  "emoji": null,
                                  "is_paid": false
                                },
                                {
                                  "count": 13000,
                                  "custom_emoji_id": "5373223594484587136",
                                  "emoji": null,
                                  "is_paid": false
                                }
                              ],
                              "reply_to": null,
                              "sender_name": null,
                              "signature": "Pavel Durov"
                            }
                          },
                          "platform_type": "gif",
                          "published_at": "2026-10-10T14:22:43Z",
                          "text": "💸 If your wallet doesn’t look like this, don’t even bother sending me money for my  birthday! 🎂",
                          "thumbnail_url": "https://cdn4.telesco.pe/file/ef2H_OWJLC-8LfDhQZQeyxdbbsqG5TdelWDugA19pQHkmAfgw_D3-7J6IVVDA2fKbPalVY8lO-7r1ZNdvtTWuzX-eIsqZGQOsgzJ6lFD4e23w4ItpaCcpzoLbzh-kiCktnhnqxq1rR2Ul7qSEwa1NDz5byYymI8W_b9JsNkBkrlVreXDBWU2l9wLQ3iKOYB2VulCHtP-2o-iDaYCTe7jKnLIBmKQICXKPOvdBwIWIMLGvG0VEnsXeYK_oZv…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://t.me/durov/551"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count",
                            "platform_specific.telegram.reactions[].count"
                          ],
                          "author": {
                            "avatar_url": "https://cdn4.telesco.pe/file/AM3EaKY4OWoCIpqIJGL2G4hcjBupbm4OuzSyAnEGF2gBOPJJIYOcnXbjDpqmilOWXXjheFFey4oGODL1BybYTdbTaJHo9qb3KEAIw9y3VvSrrKwoRdfBHWovcRqFmFEu5EeKeGrOZPTVcZEHBP6rbBp5qM4WbNdvEbGQLAnCPle0ArPYn70dJpY8D3zpJWbhZ2V1bnF2k0VXfyWUnokwHk6Q56QkaNg5gs1PhbGSaPshnBDj1xw7QOhLE-o…",
                            "display_name": "Pavel Durov",
                            "id": "durov",
                            "is_verified": true,
                            "url": "https://t.me/durov",
                            "username": "durov"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "durov/548",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 79800,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 4050000
                          },
                          "platform": "telegram",
                          "platform_specific": {
                            "telegram": {
                              "buttons": [],
                              "channel_id": "1006503122",
                              "document": null,
                              "forwarded_from": null,
                              "is_edited": false,
                              "link_preview": {
                                "description": "Hi, Codeforces!",
                                "image_url": "https://cdn4.telesco.pe/file/J3y4bSZ0MHHlOkGwzSlBok60Tw37kivBKJ7T8Anxhp0FMCBDS0J9Oi1qLkbKZ5ZQftp0vkQk6oWOPOwAHj7Uhz-_8DHPVW3bLnnystop-iVEZw3OnAJhWmGtJYMYM5CQkhyVLsZmLDWYqar1LsmfgjmH4z8d6YdBtvskULNJPNqOgqwHcH_wWsFsiwoy1WfU4PJUBtuW-zTTdws2jYUkW8LfhAmdjlDQTNloy9jqg6vEaDzaI09vXQpm9rO…",
                                "site_name": "Codeforces",
                                "title": "Telegram Returns as Title Sponsor of Codeforces!",
                                "url": "https://codeforces.com/blog/entry/156620"
                              },
                              "links": [
                                "https://codeforces.com/blog/entry/156620"
                              ],
                              "message_id": 548,
                              "poll": null,
                              "reactions": [
                                {
                                  "count": 21900,
                                  "custom_emoji_id": null,
                                  "emoji": null,
                                  "is_paid": true
                                },
                                {
                                  "count": 36900,
                                  "custom_emoji_id": "5399847211989246390",
                                  "emoji": null,
                                  "is_paid": false
                                },
                                {
                                  "count": 10800,
                                  "custom_emoji_id": "5936157098181135162",
                                  "emoji": null,
                                  "is_paid": false
                                }
                              ],
                              "reply_to": null,
                              "sender_name": null,
                              "signature": "Pavel Durov"
                            }
                          },
                          "platform_type": "message",
                          "published_at": "2026-09-11T16:04:02Z",
                          "text": "🤝 Telegram has become the sponsor of Codeforces — the largest competitive programming platform in the world. \n\n ⚡CodeForces organizes over 100 coding contests every year and has 4 million contestants signed up.\n\n🌱 Since 2010, I've supported Codeforces through the companies I star…",
                          "thumbnail_url": "https://cdn4.telesco.pe/file/J3y4bSZ0MHHlOkGwzSlBok60Tw37kivBKJ7T8Anxhp0FMCBDS0J9Oi1qLkbKZ5ZQftp0vkQk6oWOPOwAHj7Uhz-_8DHPVW3bLnnystop-iVEZw3OnAJhWmGtJYMYM5CQkhyVLsZmLDWYqar1LsmfgjmH4z8d6YdBtvskULNJPNqOgqwHcH_wWsFsiwoy1WfU4PJUBtuW-zTTdws2jYUkW8LfhAmdjlDQTNloy9jqg6vEaDzaI09vXQpm9rO…",
                          "title": null,
                          "type": "link",
                          "unknown_fields": [],
                          "url": "https://t.me/durov/548"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "telegram",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 417,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "durov",
                          "url": "https://t.me/durov"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TelegramChannel_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Full history with views and reactions",
        "tags": [
          "Telegram"
        ],
        "x-socialtap-endpoint": "telegram.channel_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "page_max": 20,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/telegram/post": {
      "get": {
        "description": "Returns one post of a public Telegram channel or group from its t.me link, with its text, media, views and reactions. It also has the links, hashtags and mentions in it, its date, photos, albums, videos, voice messages and stickers with their files, its poll, link preview and file, what it was forwarded from or replies to, whether it was edited, its signature, and the channel's numeric ID. Accepts links on t.me, telegram.me and telegram.dog, or the post's id.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\nIn Telegram's words: `metrics.like_count` is reactions.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/telegram/post/ (Markdown: https://socialtap.dev/docs/reference/telegram/post/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/telegram/post/index.md)",
          "url": "https://socialtap.dev/docs/reference/telegram/post/"
        },
        "operationId": "telegram.post.get",
        "parameters": [
          {
            "description": "A Telegram post: its link (t.me/<name>/<number>, also on telegram.me and telegram.dog, the channel page's t.me/s/<name>/<number>, a forum topic's t.me/<name>/<topic>/<number>, the account's own host <name>.t.me/<number>, with any query) or its id as this API writes it (<name>/<number>). A private chat's link (t.me/c/...) only its members can read: it is refused.",
            "example": "https://t.me/durov/546",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "A Telegram post: its link (t.me/<name>/<number>, also on telegram.me and telegram.dog, the channel page's t.me/s/<name>/<number>, a forum topic's t.me/<name>/<topic>/<number>, the account's own host <name>.t.me/<number>, with any query) or its id as this API writes it (<name>/<number>). A private chat's link (t.me/c/...) only its members can read: it is refused.",
              "examples": [
                "https://t.me/durov/546"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "metrics.view_count",
                          "metrics.like_count",
                          "platform_specific.telegram.reactions[].count"
                        ],
                        "author": {
                          "avatar_url": "https://cdn4.telesco.pe/file/AM3EaKY4OWoCIpqIJGL2G4hcjBupbm4OuzSyAnEGF2gBOPJJIYOcnXbjDpqmilOWXXjheFFey4oGODL1BybYTdbTaJHo9qb3KEAIw9y3VvSrrKwoRdfBHWovcRqFmFEu5EeKeGrOZPTVcZEHBP6rbBp5qM4WbNdvEbGQLAnCPle0ArPYn70dJpY8D3zpJWbhZ2V1bnF2k0VXfyWUnokwHk6Q56QkaNg5gs1PhbGSaPshnBDj1xw7QOhLE-o…",
                          "display_name": "Pavel Durov",
                          "id": "durov",
                          "is_verified": true,
                          "url": "https://t.me/durov",
                          "username": "durov"
                        },
                        "coauthors": [],
                        "duration_ms": 20000,
                        "hashtags": [],
                        "id": "durov/546",
                        "is_nsfw": null,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": null,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": 20000,
                            "expires_at": null,
                            "height": 1920,
                            "thumbnail_url": "https://cdn4.telesco.pe/file/oSUZWQy5ajo9qNzPTyVfWPmynW0e-n68CIbR2KJvGHXnnmSLUlvzUGAE3bGypAec9zc8kk1sHdcB0soW00CX-tKMVdzpwisCSYN_ZGrIBu9T637jvBhDK6eG8TLUWI7J9TyTGa5Y7qk3U3meRc7EBvCBrz-HyX61s0SkkfG-akkNQH1bm-ZOLdUKGsKIN2MmVccLPNINVf3cdzMiJcta6zKY1hLXMGAzeV45qpPy1MEGGmYJmhwsuareyIN…",
                            "type": "video",
                            "url": "https://cdn4.telesco.pe/file/e0b2769474.mp4?token=SCRUBBED",
                            "width": 1920
                          }
                        ],
                        "mentions": [],
                        "metrics": {
                          "comment_count": null,
                          "like_count": 80950,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": null,
                          "share_count": null,
                          "view_count": 4280000
                        },
                        "platform": "telegram",
                        "platform_specific": {
                          "telegram": {
                            "buttons": [],
                            "channel_id": "1006503122",
                            "document": null,
                            "forwarded_from": null,
                            "is_edited": false,
                            "link_preview": null,
                            "links": [],
                            "message_id": 546,
                            "poll": null,
                            "reactions": [
                              {
                                "count": 35700,
                                "custom_emoji_id": null,
                                "emoji": null,
                                "is_paid": true
                              },
                              {
                                "count": 28400,
                                "custom_emoji_id": "5399847211989246390",
                                "emoji": null,
                                "is_paid": false
                              },
                              {
                                "count": 9350,
                                "custom_emoji_id": "5373223594484587136",
                                "emoji": null,
                                "is_paid": false
                              }
                            ],
                            "reply_to": null,
                            "sender_name": null,
                            "signature": "Pavel Durov"
                          }
                        },
                        "platform_type": "video",
                        "published_at": "2026-08-31T16:30:15Z",
                        "text": "🏳️ Gram Wallet in Telegram is ready and is now accessible to a select group of users.\n\n🤩 We'll be gradually rolling it out to our billion+ users over the next couple of weeks.\n\n⚡️ Thanks to the validators who approved the smart contract that powers it, future upgrades of the wall…",
                        "thumbnail_url": "https://cdn4.telesco.pe/file/oSUZWQy5ajo9qNzPTyVfWPmynW0e-n68CIbR2KJvGHXnnmSLUlvzUGAE3bGypAec9zc8kk1sHdcB0soW00CX-tKMVdzpwisCSYN_ZGrIBu9T637jvBhDK6eG8TLUWI7J9TyTGa5Y7qk3U3meRc7EBvCBrz-HyX61s0SkkfG-akkNQH1bm-ZOLdUKGsKIN2MmVccLPNINVf3cdzMiJcta6zKY1hLXMGAzeV45qpPy1MEGGmYJmhwsuareyIN…",
                        "title": null,
                        "type": "video",
                        "unknown_fields": [],
                        "url": "https://t.me/durov/546"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "telegram",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 321,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "durov/546",
                          "url": "https://t.me/durov/546"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TelegramPostResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Views, reactions, media and forwards",
        "tags": [
          "Telegram"
        ],
        "x-socialtap-endpoint": "telegram.post",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/telegram/search_channels": {
      "get": {
        "description": "Finds public Telegram channels by topic, niche or name through a web search, one result per channel with its username and link. Name, bio and subscriber count come with it where the search index shows them. Add fill=true to get each channel's full, current record in the same response: exact subscribers, photo, badge, creation date, numeric ID, and whether it is a channel or a group. Page through the results with the cursor.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/telegram/search_channels/ (Markdown: https://socialtap.dev/docs/reference/telegram/search_channels/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/telegram/search_channels/index.md)",
          "url": "https://socialtap.dev/docs/reference/telegram/search_channels/"
        },
        "operationId": "telegram.search_channels.list",
        "parameters": [
          {
            "description": "Words to find Telegram channels by, as a web search reads them: a topic, a niche, a channel's name (crypto news, golang jobs, \"the block\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint.",
            "example": "crypto news channel",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find Telegram channels by, as a web search reads them: a topic, a niche, a channel's name (crypto news, golang jobs, \"the block\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint.",
              "examples": [
                "crypto news channel"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://t.me/CryptoRankNews",
                          "place": null,
                          "platform": "telegram",
                          "platform_specific": {},
                          "position": 0,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "The official channel of CryptoRank.io platform Business request: @CryptoRank_BDtm Community chat - @CryptoRankEn Support - @cryptorank_io_sup СНГ чат - @cryptorank_ru Twitter x.com/CryptoRank_io",
                            "display_name": null,
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": null,
                              "following_count": null,
                              "post_count": null,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://t.me/CryptoRankNews",
                            "username": "CryptoRankNews"
                          },
                          "snippet": "The official channel of CryptoRank.io platform Business request: @CryptoRank_BDtm Community chat - @CryptoRankEn Support - @cryptorank_io_sup СНГ чат - @cryptorank_ru Twitter x.com/CryptoRank_io",
                          "sound": null,
                          "title": "Telegram: View @CryptoRankNews",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://t.me/CryptoRankNews"
                        },
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://t.me/ptktck",
                          "place": null,
                          "platform": "telegram",
                          "platform_specific": {},
                          "position": 1,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "Coins research, crypto news from PTKTCK team - Website: https://ptktck.com/ - Group Chat: https://t.me/ptktckgr - Fanpage: https://www.fb.com/ptktck - Group Facebook: https://www.fb.com/groups/ptktck",
                            "display_name": "PTKTCK - Coin Research | Crypto News Channel",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": null,
                              "following_count": null,
                              "post_count": null,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://t.me/ptktck",
                            "username": "ptktck"
                          },
                          "snippet": "Coins research, crypto news from PTKTCK team - Website: https://ptktck.com/ - Group Chat: https://t.me/ptktckgr - Fanpage: https://www.fb.com/ptktck - Group Facebook: https://www.fb.com/groups/ptktck",
                          "sound": null,
                          "title": "PTKTCK - Coin Research | Crypto News Channel",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://t.me/ptktck"
                        },
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://t.me/s/Finance",
                          "place": null,
                          "platform": "telegram",
                          "platform_specific": {},
                          "position": 2,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": null,
                            "display_name": "Money 💰 Crypto & Finance",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": null,
                              "following_count": null,
                              "post_count": null,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://t.me/Finance",
                            "username": "Finance"
                          },
                          "snippet": "💰 #1 Crypto & Finance Channel on Telegram ⚡ Breaking crypto news first 📊 Bitcoin & altcoin signals 🐋 Whale alerts & on-chain data 💎 Airdrops, listings & alpha BTC ETH SOL | DeFi NFT Web3 🔔 Turn on notifications",
                          "sound": null,
                          "title": "Money 💰 Crypto & Finance",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://t.me/Finance"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "telegram",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1222,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TelegramSearch_channelsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Channels for any topic, niche or name",
        "tags": [
          "Telegram"
        ],
        "x-socialtap-endpoint": "telegram.search_channels",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/threads/comments": {
      "get": {
        "description": "Returns the public replies to a Threads post, newest first, from its link, short link, code or numeric ID. Each reply has its text, the author with their verified badge, the exact posting time, like, reply, repost and quote counts, and the language Threads detected. It also says whether the reply is pinned or edited, and whether the post's author liked or wrote it. Use since and until to read only a time window.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Comment` items (the shared schema, the same on every platform), newest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/threads/comments/ (Markdown: https://socialtap.dev/docs/reference/threads/comments/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/threads/comments/index.md)",
          "url": "https://socialtap.dev/docs/reference/threads/comments/"
        },
        "operationId": "threads.comments.list",
        "parameters": [
          {
            "description": "Threads post URL (threads.com or threads.net: /@user/post/<code>, its /media, /embed or other views, or the short /t/<code> link) or a bare post: its 11-character code or its numeric ID. A reply's URL lists that reply's own replies.",
            "example": "https://www.threads.com/@zuck/post/DeZtp-TkQHh",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Threads post URL (threads.com or threads.net: /@user/post/<code>, its /media, /embed or other views, or the short /t/<code> link) or a bare post: its 11-character code or its numeric ID. A reply's URL lists that reply's own replies.",
              "examples": [
                "https://www.threads.com/@zuck/post/DeZtp-TkQHh"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at (exact): the list is newest first, so the walk stops at the first older reply and later pages are not fetched.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at (exact): the list is newest first, so the walk stops at the first older reply and later pages are not fetched.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-19/600353339_17931124017119832_1842067081437827711_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=107&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_gid…",
                            "display_name": "陳宏浩",
                            "id": "63413103831",
                            "is_verified": false,
                            "url": "https://www.threads.com/@g14leo7",
                            "username": "g14leo7"
                          },
                          "edited_at": null,
                          "id": "DfNBr6ikvs7",
                          "is_by_post_author": false,
                          "is_edited": false,
                          "is_liked_by_author": false,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": 1,
                            "reply_count": 0
                          },
                          "parent_id": null,
                          "platform": "threads",
                          "platform_specific": {
                            "threads": {
                              "language": "zh-TW",
                              "quote_count": 0,
                              "repost_count": 1
                            }
                          },
                          "post_id": "DeZtp-TkQHh",
                          "published_at": "2026-11-01T15:12:46Z",
                          "text": "投票 為什麼宣傳量這麼少",
                          "unknown_fields": [],
                          "url": "https://www.threads.com/@g14leo7/post/DfNBr6ikvs7"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/884940290_17919199281535263_8626428927104914186_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=101&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid…",
                            "display_name": "Youtty",
                            "id": "75926319262",
                            "is_verified": false,
                            "url": "https://www.threads.com/@youtty._.0106",
                            "username": "youtty._.0106"
                          },
                          "edited_at": null,
                          "id": "DfNAvsPjwNx",
                          "is_by_post_author": false,
                          "is_edited": false,
                          "is_liked_by_author": false,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": 0,
                            "reply_count": 0
                          },
                          "parent_id": null,
                          "platform": "threads",
                          "platform_specific": {
                            "threads": {
                              "language": "en",
                              "quote_count": 0,
                              "repost_count": 0
                            }
                          },
                          "post_id": "DeZtp-TkQHh",
                          "published_at": "2026-11-01T15:04:33Z",
                          "text": "憨仔講中文",
                          "unknown_fields": [],
                          "url": "https://www.threads.com/@youtty._.0106/post/DfNAvsPjwNx"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.89012-19/573323465_1219825463302212_7278921664109726296_n.jpg?stp=dst-jpg_tt6&_nc_cat=1&ig_cache_key=YW5vbnltb3VzX3Byb2ZpbGVfcGlj.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=s…",
                            "display_name": "SUNITHA KC",
                            "id": "21006306393",
                            "is_verified": false,
                            "url": "https://www.threads.com/@sunitha953092",
                            "username": "sunitha953092"
                          },
                          "edited_at": null,
                          "id": "DfMX5oZE-NQ",
                          "is_by_post_author": false,
                          "is_edited": false,
                          "is_liked_by_author": false,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": 0,
                            "reply_count": 0
                          },
                          "parent_id": null,
                          "platform": "threads",
                          "platform_specific": {
                            "threads": {
                              "language": "en",
                              "quote_count": 0,
                              "repost_count": 0
                            }
                          },
                          "post_id": "DeZtp-TkQHh",
                          "published_at": "2026-11-01T09:07:39Z",
                          "text": "Amazing 🌹",
                          "unknown_fields": [],
                          "url": "https://www.threads.com/@sunitha953092/post/DfMX5oZE-NQ"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "threads",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 905,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "DeZtp-TkQHh",
                          "url": "https://www.threads.com/t/DeZtp-TkQHh"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ThreadsCommentsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Replies to a public post, newest first",
        "tags": [
          "Threads"
        ],
        "x-socialtap-endpoint": "threads.comments",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 1800,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/threads/post": {
      "get": {
        "description": "Returns a public Threads post or reply from its link, share link, shortcode or numeric ID, with exact like, reply, repost, quote and share counts. It also has the text with mentions and hashtags, the exact publish time, the author, every photo, video, carousel item or GIF, the link card, the topic tag, and the post it quotes or the account it replies to.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/threads/post/ (Markdown: https://socialtap.dev/docs/reference/threads/post/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/threads/post/index.md)",
          "url": "https://socialtap.dev/docs/reference/threads/post/"
        },
        "operationId": "threads.post.get",
        "parameters": [
          {
            "description": "Threads post URL (threads.com or threads.net: /@user/post/<code>, its /media or other views, or the /t/<code> share link), a post's 11-character shortcode, or its numeric ID.",
            "example": "https://www.threads.com/@zuck/post/DeZtp-TkQHh",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "Threads post URL (threads.com or threads.net: /@user/post/<code>, its /media or other views, or the /t/<code> share link), a post's 11-character shortcode, or its numeric ID.",
              "examples": [
                "https://www.threads.com/@zuck/post/DeZtp-TkQHh"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/825322135_17989325280103224_1252773933700107438_n.jpg?stp=dst-jpg_s206x206_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=S…",
                          "display_name": "Mark Zuckerberg",
                          "id": "63055343223",
                          "is_verified": true,
                          "url": "https://www.threads.com/@zuck",
                          "username": "zuck"
                        },
                        "coauthors": [],
                        "duration_ms": null,
                        "hashtags": [],
                        "id": "DeZtp-TkQHh",
                        "is_nsfw": null,
                        "is_pinned": false,
                        "is_sponsored": null,
                        "language": "en",
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": null,
                            "expires_at": "2026-10-25T18:00:00Z",
                            "height": 3260,
                            "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/844965867_17991705567103224_8296143909108287920_n.webp?_nc_cat=109&ig_cache_key=NDAwNjQzNDE0MDAxNDU3NjA5Nw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-…",
                            "type": "image",
                            "url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/844965867_17991705567103224_8296143909108287920_n.webp?_nc_cat=109&ig_cache_key=NDAwNjQzNDE0MDAxNDU3NjA5Nw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-…",
                            "width": 2160
                          }
                        ],
                        "mentions": [],
                        "metrics": {
                          "comment_count": 649,
                          "like_count": 2194,
                          "quote_count": 62,
                          "repost_count": 176,
                          "save_count": null,
                          "share_count": 150,
                          "view_count": null
                        },
                        "platform": "threads",
                        "platform_specific": {
                          "threads": {
                            "is_edited": false,
                            "is_reply": false,
                            "is_spoiler": false,
                            "link": null,
                            "numeric_id": "4006434140014576097",
                            "quoted_post": null,
                            "reply_control": "everyone",
                            "reply_to_author": null,
                            "topic_tag": null
                          }
                        },
                        "platform_type": "thread",
                        "published_at": "2026-10-12T16:56:29Z",
                        "text": "Introducing Muse Wonder, our new family of frontier models with state of the art performance for personal and professional agentic work.",
                        "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/844965867_17991705567103224_8296143909108287920_n.webp?_nc_cat=109&ig_cache_key=NDAwNjQzNDE0MDAxNDU3NjA5Nw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-…",
                        "title": null,
                        "type": "image",
                        "unknown_fields": [],
                        "url": "https://www.threads.com/@zuck/post/DeZtp-TkQHh"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "threads",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 268,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "DeZtp-TkQHh",
                          "url": "https://www.threads.com/@zuck/post/DeZtp-TkQHh"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ThreadsPostResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Post or reply with exact likes and reposts",
        "tags": [
          "Threads"
        ],
        "x-socialtap-endpoint": "threads.post",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/threads/posts": {
      "get": {
        "description": "Returns a public Threads account's posts, pinned first and then newest first, from its username, numeric ID or profile link. Each post has its text, publish time, images, videos with their length, carousels, link cards, quoted posts, topic tags, mentions, and exact like, reply, repost, quote and share counts. Page back through the account's whole history.\n\nReturns `{data, page, meta}`: `data` holds up to 25 `Post` items (the shared schema, the same on every platform), newest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/threads/posts/ (Markdown: https://socialtap.dev/docs/reference/threads/posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/threads/posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/threads/posts/"
        },
        "operationId": "threads.posts.list",
        "parameters": [
          {
            "description": "Threads username with or without the @ (zuck, @zuck), the account's numeric id, or a threads.com or threads.net profile link, with any tab (/replies, /media) or query. A number of 5 or more digits is an account id; @ before it is a username.",
            "example": "zuck",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Threads username with or without the @ (zuck, @zuck), the account's numeric id, or a threads.com or threads.net profile link, with any tab (/replies, /media) or query. A number of 5 or more digits is an account id; @ before it is a username.",
              "examples": [
                "zuck"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 25,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 25,
              "maximum": 25,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/825322135_17989325280103224_1252773933700107438_n.jpg?stp=dst-jpg_s206x206_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=S…",
                            "display_name": "Mark Zuckerberg",
                            "id": "63055343223",
                            "is_verified": true,
                            "url": "https://www.threads.com/@zuck",
                            "username": "zuck"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "DfNR0zhEdWv",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 2849,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/879845210_17995497813103224_7602527028515417661_n.webp?_nc_cat=1&ig_cache_key=NDAyMDk0ODM5OTM3MjQ5NTg5OA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-at…",
                              "type": "image",
                              "url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/879845210_17995497813103224_7602527028515417661_n.webp?_nc_cat=1&ig_cache_key=NDAyMDk0ODM5OTM3MjQ5NTg5OA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-at…",
                              "width": 2279
                            },
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 2711,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/873072173_17995497822103224_7662939010019123382_n.webp?_nc_cat=1&ig_cache_key=NDAyMDk0ODM5OTM1NTY2MjA2MQ%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-at…",
                              "type": "image",
                              "url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/873072173_17995497822103224_7662939010019123382_n.webp?_nc_cat=1&ig_cache_key=NDAyMDk0ODM5OTM1NTY2MjA2MQ%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-at…",
                              "width": 2169
                            },
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 2856,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/881058863_17995497831103224_8682002515740687938_n.webp?_nc_cat=1&ig_cache_key=NDAyMDk0ODM5OTU2NTMxOTYyMw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-at…",
                              "type": "image",
                              "url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/881058863_17995497831103224_8682002515740687938_n.webp?_nc_cat=1&ig_cache_key=NDAyMDk0ODM5OTU2NTMxOTYyMw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-at…",
                              "width": 2142
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 504,
                            "like_count": 1931,
                            "quote_count": 18,
                            "repost_count": 75,
                            "save_count": null,
                            "share_count": 74,
                            "view_count": null
                          },
                          "platform": "threads",
                          "platform_specific": {
                            "threads": {
                              "is_edited": false,
                              "is_reply": false,
                              "is_spoiler": false,
                              "link": null,
                              "numeric_id": "4020948437830849967",
                              "quoted_post": null,
                              "reply_control": "everyone",
                              "reply_to_author": null,
                              "topic_tag": null
                            }
                          },
                          "platform_type": "thread",
                          "published_at": "2026-11-01T17:33:48Z",
                          "text": "Tried to get the family to dress as burger night, but couldn't corral the littlest burger",
                          "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/879845210_17995497813103224_7602527028515417661_n.webp?_nc_cat=1&ig_cache_key=NDAyMDk0ODM5OTM3MjQ5NTg5OA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-at…",
                          "title": null,
                          "type": "carousel",
                          "unknown_fields": [],
                          "url": "https://www.threads.com/@zuck/post/DfNR0zhEdWv"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/825322135_17989325280103224_1252773933700107438_n.jpg?stp=dst-jpg_s206x206_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=S…",
                            "display_name": "Mark Zuckerberg",
                            "id": "63055343223",
                            "is_verified": true,
                            "url": "https://www.threads.com/@zuck",
                            "username": "zuck"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "DeZtp-TkQHh",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 3260,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/844965867_17991705567103224_8296143909108287920_n.webp?_nc_cat=109&ig_cache_key=NDAwNjQzNDE0MDAxNDU3NjA5Nw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-…",
                              "type": "image",
                              "url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/844965867_17991705567103224_8296143909108287920_n.webp?_nc_cat=109&ig_cache_key=NDAwNjQzNDE0MDAxNDU3NjA5Nw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-…",
                              "width": 2160
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 651,
                            "like_count": 2198,
                            "quote_count": 62,
                            "repost_count": 176,
                            "save_count": null,
                            "share_count": 150,
                            "view_count": null
                          },
                          "platform": "threads",
                          "platform_specific": {
                            "threads": {
                              "is_edited": false,
                              "is_reply": false,
                              "is_spoiler": false,
                              "link": null,
                              "numeric_id": "4006434140014576097",
                              "quoted_post": null,
                              "reply_control": "everyone",
                              "reply_to_author": null,
                              "topic_tag": null
                            }
                          },
                          "platform_type": "thread",
                          "published_at": "2026-10-12T16:56:29Z",
                          "text": "Introducing Muse Wonder, our new family of frontier models with state of the art performance for personal and professional agentic work.",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/844965867_17991705567103224_8296143909108287920_n.webp?_nc_cat=109&ig_cache_key=NDAwNjQzNDE0MDAxNDU3NjA5Nw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://www.threads.com/@zuck/post/DeZtp-TkQHh"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/825322135_17989325280103224_1252773933700107438_n.jpg?stp=dst-jpg_s206x206_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=S…",
                            "display_name": "Mark Zuckerberg",
                            "id": "63055343223",
                            "is_verified": true,
                            "url": "https://www.threads.com/@zuck",
                            "username": "zuck"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "DeZgeQhm6RW",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 2000,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/843592055_17991691623103224_8086321653765802754_n.webp?_nc_cat=102&ig_cache_key=NDAwNjM3NjE2MDMzOTE0MTcxOA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-…",
                              "type": "image",
                              "url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/843592055_17991691623103224_8086321653765802754_n.webp?_nc_cat=102&ig_cache_key=NDAwNjM3NjE2MDMzOTE0MTcxOA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-…",
                              "width": 1500
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 518,
                            "like_count": 1648,
                            "quote_count": 38,
                            "repost_count": 114,
                            "save_count": null,
                            "share_count": 72,
                            "view_count": null
                          },
                          "platform": "threads",
                          "platform_specific": {
                            "threads": {
                              "is_edited": false,
                              "is_reply": false,
                              "is_spoiler": false,
                              "link": null,
                              "numeric_id": "4006376160339141718",
                              "quoted_post": null,
                              "reply_control": "everyone",
                              "reply_to_author": null,
                              "topic_tag": null
                            }
                          },
                          "platform_type": "thread",
                          "published_at": "2026-10-12T15:01:17Z",
                          "text": "Muse ordered me 🍉 how thoughtful!",
                          "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/843592055_17991691623103224_8086321653765802754_n.webp?_nc_cat=102&ig_cache_key=NDAwNjM3NjE2MDMzOTE0MTcxOA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://www.threads.com/@zuck/post/DeZgeQhm6RW"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "threads",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1150,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "63055343223",
                          "url": "https://www.threads.com/@zuck"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ThreadsPostsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Pinned first, with exact likes, replies and reposts",
        "tags": [
          "Threads"
        ],
        "x-socialtap-endpoint": "threads.posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "page_max": 25,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/threads/profile": {
      "get": {
        "description": "Returns a public Threads profile from a username, numeric ID or profile link: exact follower count, bio, bio links, name and verified badge. It also has the user ID, the largest profile picture, whether the account is private, the topic labels Threads shows on the profile, and which bio links Threads marks verified.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/threads/profile/ (Markdown: https://socialtap.dev/docs/reference/threads/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/threads/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/threads/profile/"
        },
        "operationId": "threads.profile.get",
        "parameters": [
          {
            "description": "Threads username with or without the @ (zuck, @zuck), the account's numeric id, or a profile link (threads.com/@zuck, threads.net/@zuck, with or without a tab such as /replies, /reposts or /media, and with any query such as ?hl=es). Usernames are case-insensitive. A number of 5 or more digits is an account id; @ before it is a username.",
            "example": "https://www.threads.com/@zuck",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "Threads username with or without the @ (zuck, @zuck), the account's numeric id, or a profile link (threads.com/@zuck, threads.net/@zuck, with or without a tab such as /replies, /reposts or /media, and with any query such as ?hl=es). Usernames are case-insensitive. A number of 5 or more digits is an account id; @ before it is a username.",
              "examples": [
                "zuck"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-19/825322135_17989325280103224_1252773933700107438_n.jpg?stp=dst-jpg_s640x640_tt6&_nc_cat=107&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_gid…",
                        "banner_url": null,
                        "bio": "Mostly superintelligence and MMA takes",
                        "category": null,
                        "country_code": null,
                        "created_at": null,
                        "display_name": "Mark Zuckerberg",
                        "external_links": [],
                        "id": "63055343223",
                        "is_private": false,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 5751366,
                          "following_count": null,
                          "post_count": null,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "threads",
                        "platform_specific": {
                          "threads": {
                            "interest_tags": [
                              "AI Threads",
                              "UFC Threads",
                              "AI"
                            ],
                            "verified_link_urls": []
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://www.threads.com/@zuck",
                        "username": "zuck"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "threads",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 409,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "63055343223",
                          "url": "https://www.threads.com/@zuck"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ThreadsProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact follower count, bio and bio links",
        "tags": [
          "Threads"
        ],
        "x-socialtap-endpoint": "threads.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/threads/search_posts": {
      "get": {
        "description": "Returns the public Threads posts that match a keyword, by best match or newest first, as Threads shows them to a signed-out visitor. Each post has its link, text, publish time, language, topic tag, mentions, photos and videos, author, the post it quotes, its link card, and exact like, reply, repost, quote and share counts.\n\nReturns `{data, page, meta}`: `data` holds up to 20 `Post` items (the shared schema, the same on every platform), Threads' best matches (its search ranking) with sort=relevance (the default), newest first with sort=newest. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/threads/search_posts/ (Markdown: https://socialtap.dev/docs/reference/threads/search_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/threads/search_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/threads/search_posts/"
        },
        "operationId": "threads.search_posts.list",
        "parameters": [
          {
            "description": "Keywords, matched by Threads' own search against post text, topic tags and authors. An @ is read as a space and invisible formatting characters are dropped: signed out, Threads finds nothing for a query that has either. A quoted phrase finds nothing.",
            "example": "coffee",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Keywords, matched by Threads' own search against post text, topic tags and authors. An @ is read as a space and invisible formatting characters are dropped: signed out, Threads finds nothing for a query that has either. A quoted phrase finds nothing.",
              "examples": [
                "coffee"
              ],
              "maxLength": 500,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. relevance (default): Threads' best matches across all time. newest: Threads' fresh results (what its search box shows first), ordered newest first.",
            "example": "newest",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "relevance",
              "description": "Order of the results. relevance (default): Threads' best matches across all time. newest: Threads' fresh results (what its search box shows first), ordered newest first.",
              "enum": [
                "relevance",
                "newest"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Filters the page by published_at; Threads' logged-out search has no date filter of its own.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Filters the page by published_at; Threads' logged-out search has no date filter of its own.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 20,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/759477793_18059621363541028_3789541923716749008_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=111&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid…",
                            "display_name": "Mr. A",
                            "id": "46261141027",
                            "is_verified": false,
                            "url": "https://www.threads.com/@i.mr.a",
                            "username": "i.mr.a"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "DdmPjz5kZrr",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 2000,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/819629597_18073309220541028_6188555530352921490_n.webp?_nc_cat=104&ig_cache_key=Mzk5MTk0NjU1MTMxNjU1MjQyNw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-…",
                              "type": "image",
                              "url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/819629597_18073309220541028_6188555530352921490_n.webp?_nc_cat=104&ig_cache_key=Mzk5MTk0NjU1MTMxNjU1MjQyNw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-…",
                              "width": 1500
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 6,
                            "like_count": 52,
                            "quote_count": 0,
                            "repost_count": 0,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "threads",
                          "platform_specific": {
                            "threads": {
                              "is_edited": false,
                              "is_reply": false,
                              "is_spoiler": false,
                              "link": null,
                              "numeric_id": "3991946551316552427",
                              "quoted_post": null,
                              "reply_control": "everyone",
                              "reply_to_author": null,
                              "topic_tag": null
                            }
                          },
                          "platform_type": "thread",
                          "published_at": "2026-09-22T17:12:14Z",
                          "text": "Coffee?! 🇶🇦",
                          "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/819629597_18073309220541028_6188555530352921490_n.webp?_nc_cat=104&ig_cache_key=Mzk5MTk0NjU1MTMxNjU1MjQyNw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&_nc_ht=scontent-…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://www.threads.com/@i.mr.a/post/DdmPjz5kZrr"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/651753094_17890020600440175_7122009252380664590_n.jpg?stp=dst-jpg_s206x206_tt6&_nc_cat=102&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid…",
                            "display_name": "Jewel Cortez",
                            "id": "73411528174",
                            "is_verified": false,
                            "url": "https://www.threads.com/@_ja.crtz",
                            "username": "_ja.crtz"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "DTfqY4mkhjk",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 2160,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/613172382_17882560644440175_7420895248994580899_n.jpg?stp=cp6_dst-jpg_e35_tt6&_nc_cat=101&ig_cache_key=MzgwOTk1MDIzMjM0ODkwMjAwNg%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc…",
                              "type": "image",
                              "url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/613172382_17882560644440175_7420895248994580899_n.jpg?stp=cp6_dst-jpg_e35_tt6&_nc_cat=101&ig_cache_key=MzgwOTk1MDIzMjM0ODkwMjAwNg%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc…",
                              "width": 1215
                            },
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/613275726_17882560653440175_5790363634609809674_n.jpg?stp=cp6_dst-jpg_e35_tt6&_nc_cat=111&ig_cache_key=MzgwOTk1MDIzMjAwNDk0ODU5MQ%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc…",
                              "type": "image",
                              "url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/613275726_17882560653440175_5790363634609809674_n.jpg?stp=cp6_dst-jpg_e35_tt6&_nc_cat=111&ig_cache_key=MzgwOTk1MDIzMjAwNDk0ODU5MQ%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc…",
                              "width": 1440
                            },
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1920,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/615864589_17882560662440175_5736983707363680729_n.jpg?stp=cp6_dst-jpg_e35_tt6&_nc_cat=106&ig_cache_key=MzgwOTk1MDIzMTg3OTEyMDU1Mw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc…",
                              "type": "image",
                              "url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/615864589_17882560662440175_5736983707363680729_n.jpg?stp=cp6_dst-jpg_e35_tt6&_nc_cat=106&ig_cache_key=MzgwOTk1MDIzMTg3OTEyMDU1Mw%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc…",
                              "width": 1440
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 3,
                            "like_count": 285,
                            "quote_count": 0,
                            "repost_count": 0,
                            "save_count": null,
                            "share_count": 4,
                            "view_count": null
                          },
                          "platform": "threads",
                          "platform_specific": {
                            "threads": {
                              "is_edited": false,
                              "is_reply": false,
                              "is_spoiler": false,
                              "link": null,
                              "numeric_id": "3809950237776287972",
                              "quoted_post": null,
                              "reply_control": "everyone",
                              "reply_to_author": null,
                              "topic_tag": null
                            }
                          },
                          "platform_type": "thread",
                          "published_at": "2026-01-14T14:38:02Z",
                          "text": "Coffeeee",
                          "thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-15/613172382_17882560644440175_7420895248994580899_n.jpg?stp=cp6_dst-jpg_e35_tt6&_nc_cat=101&ig_cache_key=MzgwOTk1MDIzMjM0ODkwMjAwNg%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc…",
                          "title": null,
                          "type": "carousel",
                          "unknown_fields": [],
                          "url": "https://www.threads.com/@_ja.crtz/post/DTfqY4mkhjk"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-19/805923376_17945684919327569_1298320812472703449_n.jpg?stp=dst-jpg_s206x206_tt6&_nc_cat=103&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_gid…",
                            "display_name": "Primo",
                            "id": "69615071568",
                            "is_verified": false,
                            "url": "https://www.threads.com/@papiprimooo",
                            "username": "papiprimooo"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "DTapuNaklWl",
                          "is_nsfw": null,
                          "is_pinned": false,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1472,
                              "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/615432282_17906614950327569_7606212469784013454_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=110&ig_cache_key=MzgwODUzOTkzMDMwMjUwMjMwOQ%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                              "type": "image",
                              "url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/615432282_17906614950327569_7606212469784013454_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=110&ig_cache_key=MzgwODUzOTkzMDMwMjUwMjMwOQ%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                              "width": 828
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 2,
                            "like_count": 363,
                            "quote_count": 0,
                            "repost_count": 1,
                            "save_count": null,
                            "share_count": 1,
                            "view_count": null
                          },
                          "platform": "threads",
                          "platform_specific": {
                            "threads": {
                              "is_edited": false,
                              "is_reply": false,
                              "is_spoiler": false,
                              "link": null,
                              "numeric_id": "3808539930302502309",
                              "quoted_post": null,
                              "reply_control": "everyone",
                              "reply_to_author": null,
                              "topic_tag": null
                            }
                          },
                          "platform_type": "thread",
                          "published_at": "2026-01-12T15:56:01Z",
                          "text": "Coffee timeee",
                          "thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-15/615432282_17906614950327569_7606212469784013454_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=110&ig_cache_key=MzgwODUzOTkzMDMwMjUwMjMwOQ%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=…",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://www.threads.com/@papiprimooo/post/DTapuNaklWl"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "threads",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 2066,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ThreadsSearch_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Public posts by keyword, best match or newest",
        "tags": [
          "Threads"
        ],
        "x-socialtap-endpoint": "threads.search_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Threads' best matches (its search ranking)",
          "orders": {
            "newest": "newest first",
            "relevance": "Threads' best matches (its search ranking)"
          },
          "page_max": 20,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/threads/search_profiles": {
      "get": {
        "description": "Returns the Threads accounts that match a name or username, in Threads' own ranking, for words in any language. Each has its user ID, username, display name, bio, profile picture, verified badge and profile link. A leading @ searches usernames. One request returns the whole list Threads ranks for the query.\n\nReturns `{data, page, meta}`: `data` holds up to 100 `Profile` items (the shared schema, the same on every platform), Threads' search ranking. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/threads/search_profiles/ (Markdown: https://socialtap.dev/docs/reference/threads/search_profiles/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/threads/search_profiles/index.md)",
          "url": "https://socialtap.dev/docs/reference/threads/search_profiles/"
        },
        "operationId": "threads.search_profiles.list",
        "parameters": [
          {
            "description": "Words to find accounts by: Threads matches them against usernames and display names, in any language and any case (nasa, mark zuckerberg, 東京). A leading @ searches usernames (@nasa).",
            "example": "nasa",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find accounts by: Threads matches them against usernames and display names, in any language and any case (nasa, mark zuckerberg, 東京). A leading @ searches usernames (@nasa).",
              "examples": [
                "nasa"
              ],
              "maxLength": 500,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 100,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/669747085_18089786557960389_922072622069351626_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid=SC…",
                          "banner_url": null,
                          "bio": "Making the seemingly impossible, possible. ✨",
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "NASA",
                          "external_links": [],
                          "id": "28829152388",
                          "is_private": null,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "threads",
                          "platform_specific": {
                            "threads": {
                              "interest_tags": [],
                              "verified_link_urls": []
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.threads.interest_tags",
                            "platform_specific.threads.verified_link_urls"
                          ],
                          "url": "https://www.threads.com/@nasa",
                          "username": "nasa"
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/775442147_17925135474400969_1913045756150209499_n.jpg?stp=dst-jpg_s206x206_tt6&_nc_cat=102&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_gid…",
                          "banner_url": null,
                          "bio": "아직포기할수 없어 기도 한다",
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": null,
                          "external_links": [],
                          "id": "72121680968",
                          "is_private": null,
                          "is_verified": false,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "threads",
                          "platform_specific": {
                            "threads": {
                              "interest_tags": [],
                              "verified_link_urls": []
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.threads.interest_tags",
                            "platform_specific.threads.verified_link_urls"
                          ],
                          "url": "https://www.threads.com/@nasajangvi",
                          "username": "nasajangvi"
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.89012-19/573323465_1219825463302212_7278921664109726296_n.jpg?stp=dst-jpg_tt6&_nc_cat=1&ig_cache_key=YW5vbnltb3VzX3Byb2ZpbGVfcGlj.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=s…",
                          "banner_url": null,
                          "bio": "U either die a hero or watch urself become the villain",
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "楊鈞翰",
                          "external_links": [],
                          "id": "63312256631",
                          "is_private": null,
                          "is_verified": false,
                          "location": null,
                          "metrics": {
                            "follower_count": null,
                            "following_count": null,
                            "post_count": null,
                            "total_like_count": null,
                            "total_view_count": null
                          },
                          "platform": "threads",
                          "platform_specific": {
                            "threads": {
                              "interest_tags": [],
                              "verified_link_urls": []
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links",
                            "platform_specific.threads.interest_tags",
                            "platform_specific.threads.verified_link_urls"
                          ],
                          "url": "https://www.threads.com/@nasa0426",
                          "username": "nasa0426"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "threads",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 543,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ThreadsSearch_profilesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Accounts by name or username, with bios",
        "tags": [
          "Threads"
        ],
        "x-socialtap-endpoint": "threads.search_profiles",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Threads' search ranking",
          "page_max": 100,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/ad": {
      "get": {
        "description": "Returns one ad from TikTok's public ad library, which holds ads shown in Europe, from its library link or ad ID. You get the advertiser and its TikTok account, who paid, the text, media and landing page, the days it ran, reach by country, age and gender, its topic and objective, and any takedown with TikTok's reason.\n\nReturns `{data, meta}`: `data` is a `Ad` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/ad/ (Markdown: https://socialtap.dev/docs/reference/tiktok/ad/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/ad/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/ad/"
        },
        "operationId": "tiktok.ad.get",
        "parameters": [
          {
            "description": "The ad's TikTok Ad Library link (library.tiktok.com/ads/detail/?ad_id=…) or its ad ID.",
            "example": "https://library.tiktok.com/ads/detail/?ad_id=1874500065342865",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The ad's TikTok Ad Library link (library.tiktok.com/ads/detail/?ad_id=…) or its ad ID.",
              "examples": [
                "https://library.tiktok.com/ads/detail/?ad_id=1874500065342865"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "advertiser": {
                          "avatar_url": "https://p16-common-sign.tiktokcdn-eu.com/tos-useast2a-avt-0068-giso/376d42e4d2d431dde2bedc5acba5ac67~tplv-tiktokx-cropcenter:168:168.jpeg?dr=10397&refresh_token=45674133&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=8aecc5ac&idc=no1a",
                          "display_name": "Hilti Deutschland AG",
                          "id": "7084134349806142470",
                          "is_verified": true,
                          "url": "https://www.tiktok.com/@hiltideutschland",
                          "username": "hiltideutschland"
                        },
                        "approximate_fields": [
                          "audience_size",
                          "first_shown_at",
                          "last_shown_at"
                        ],
                        "audience_size": {
                          "lower_bound": 2000,
                          "upper_bound": 2000
                        },
                        "country_codes": [
                          "DE"
                        ],
                        "creatives": [
                          {
                            "body": "Du baust unser Morgen. Danke für deinen Einsatz!",
                            "cta_text": "Learn more",
                            "link_description": null,
                            "link_url": "https://www.hilti.de/content/landing-page/local/brand-thanks?cinfo=pro_all_all_all_mixed_na&utm_source=tiktok&utm_medium=paid_social&utm_campaign=regional_e3_de_de_ciab-brand-image_awareness_main&utm_term=_cid_&utm_content=awareness_15sekv2_video_in-feed_int_workers",
                            "media": [
                              {
                                "alt_text": null,
                                "duration_ms": null,
                                "expires_at": null,
                                "height": null,
                                "thumbnail_url": "https://p16-common-sign.tiktokcdn.com/tos-alisg-p-0051c001-sg/oYAcmEB9C43fo29cW0sko2kiAXziEB1IAIwAEp~tplv-tiktokx-origin.jpeg?dr=14582&refresh_token=fd54107a&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=0c75dd76&shcp=9b759fb9&idc=sg1",
                                "type": "video",
                                "url": "https://library.tiktok.com/api/v1/cdn/1793762729/video/aHR0cHM6Ly92NzcudGlrdG9rY2RuLmNvbS80N2UzMzc2NDg0YmQ2NDRmYzYxMDFmYjJlNDQ0YjIzYi82YWVhZmExOC92aWRlby90b3MvdXNlYXN0MmEvdG9zLXVzZWFzdDJhLXZlLTAwNTFjNzk5LWV1dHRwL293Y0JpQUFpSUlMek1tUXcwQ0JDcG9FM1pYOWtCZkZBb0ZtMWtXLw==/9cd6d7ed-99d…",
                                "width": null
                              }
                            ],
                            "title": null
                          }
                        ],
                        "first_shown_at": "2026-09-01T00:00:00Z",
                        "id": "1874500065342865",
                        "impressions": null,
                        "is_active": null,
                        "is_political": false,
                        "languages": [],
                        "last_shown_at": "2026-11-02T00:00:00Z",
                        "paid_by": "Hilti Germany AG",
                        "platform": "tiktok",
                        "platform_specific": {
                          "tiktok": {
                            "advertiser_business_id": "7417792849774788624",
                            "advertiser_registry_location": "Germany",
                            "budget": null,
                            "category": "Home Improvement",
                            "ctr_top_percent": null,
                            "is_removed": false,
                            "like_count": null,
                            "objective": "Reach",
                            "rank": null,
                            "removal_country_codes": [],
                            "removal_reasons": [],
                            "targeting": {
                              "cities": [],
                              "countries": [
                                {
                                  "age_ranges": [
                                    "18-24",
                                    "25-34"
                                  ],
                                  "breakdown": [
                                    {
                                      "age_range": "18-24",
                                      "gender": "male",
                                      "reach": {
                                        "lower_bound": 59000,
                                        "upper_bound": 59000
                                      }
                                    },
                                    {
                                      "age_range": "18-24",
                                      "gender": "female",
                                      "reach": {
                                        "lower_bound": 94000,
                                        "upper_bound": 94000
                                      }
                                    },
                                    {
                                      "age_range": "18-24",
                                      "gender": "unknown",
                                      "reach": {
                                        "lower_bound": 0,
                                        "upper_bound": 1000
                                      }
                                    }
                                  ],
                                  "country_code": "DE",
                                  "genders": [
                                    "female",
                                    "male",
                                    "unknown"
                                  ],
                                  "reach": {
                                    "lower_bound": 313000,
                                    "upper_bound": 313000
                                  }
                                }
                              ],
                              "creator_interactions": [],
                              "device_models": [],
                              "interests": [
                                "Building"
                              ],
                              "is_audience_excluded": false,
                              "is_custom_audience": false,
                              "is_high_spending_power": false,
                              "operating_systems": [],
                              "provinces": [],
                              "video_interactions": []
                            }
                          }
                        },
                        "publisher_platforms": [
                          "tiktok"
                        ],
                        "reach": {
                          "lower_bound": 300000,
                          "upper_bound": 400000
                        },
                        "spend": null,
                        "type": "video",
                        "unknown_fields": [],
                        "url": "https://library.tiktok.com/ads/detail/?ad_id=1874500065342865"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1293,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "ad",
                          "id": "1874500065342865",
                          "url": "https://library.tiktok.com/ads/detail/?ad_id=1874500065342865"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokAdResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Targeting, reach by country and takedowns",
        "tags": [
          "TikTok Ad Library"
        ],
        "x-socialtap-endpoint": "tiktok.ad",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "ad",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/comment": {
      "get": {
        "description": "Returns one public comment or reply on a TikTok video or photo post, from a comment link or the post's link and comment_id. You get its text, exact posting time and like count, the reply count of a top-level comment, and the commenter's username, name, ID, avatar and verified badge. It also says its language, which comment it answers, and whether the creator wrote, liked or pinned it.\n\nReturns `{data, meta}`: `data` is a `Comment` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/comment/ (Markdown: https://socialtap.dev/docs/reference/tiktok/comment/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/comment/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/comment/"
        },
        "operationId": "tiktok.comment.get",
        "parameters": [
          {
            "description": "The TikTok video or photo post the comment is on: a tiktok.com/@user/video/<id> or /@user/photo/<id> link, m.tiktok.com/v/<id>.html, embed and player URLs, vm.tiktok.com/<code>, vt.tiktok.com/<code>, tiktok.com/t/<code> or a numeric video ID; or a comment link, which names the comment too: TikTok's comment share link with share_comment_id, a video link with comment_id or cid, or the app's share link of a comment (vm.tiktok.com/<code>, resolved on TikTok).",
            "example": "https://www.tiktok.com/@hankgreen1/video/7047596209028074758",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The TikTok video or photo post the comment is on: a tiktok.com/@user/video/<id> or /@user/photo/<id> link, m.tiktok.com/v/<id>.html, embed and player URLs, vm.tiktok.com/<code>, vt.tiktok.com/<code>, tiktok.com/t/<code> or a numeric video ID; or a comment link, which names the comment too: TikTok's comment share link with share_comment_id, a video link with comment_id or cid, or the app's share link of a comment (vm.tiktok.com/<code>, resolved on TikTok).",
              "examples": [
                "https://m.tiktok.com/v/6718335390845095173.html?share_comment_id=6718335906996502534&share_item_id=6718335390845095173"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "ID of the comment: any TikTok comment, top-level or reply (the id of a comment from the comments or replies endpoints). Required unless url is a comment link.",
            "example": "7047599416228234031",
            "in": "query",
            "name": "comment_id",
            "schema": {
              "description": "ID of the comment: any TikTok comment, top-level or reply (the id of a comment from the comments or replies endpoints). Required unless url is a comment link.",
              "examples": [
                "6718335906996502534"
              ],
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/da69f59aaa61f643bbccadcd2c1f5b17~tplv-tiktokx-cropcenter:100:100.jpg?dr=9640&refresh_token=1cff171d&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=30310797&shcp=ff37627b&idc=useast5",
                          "display_name": "tyler oakley",
                          "id": "52902558817587200",
                          "is_verified": true,
                          "url": "https://www.tiktok.com/@tyleroakleyish",
                          "username": "tyleroakleyish"
                        },
                        "edited_at": null,
                        "id": "7047599416228234031",
                        "is_by_post_author": false,
                        "is_edited": null,
                        "is_liked_by_author": false,
                        "is_pinned": true,
                        "metrics": {
                          "like_count": 28253,
                          "reply_count": 49
                        },
                        "parent_id": null,
                        "platform": "tiktok",
                        "platform_specific": {
                          "tiktok": {
                            "author_sec_uid": null,
                            "language": "en",
                            "thread_id": null
                          }
                        },
                        "post_id": "7047596209028074758",
                        "published_at": "2021-12-30T20:45:17Z",
                        "text": "fine I’ll be both",
                        "unknown_fields": [],
                        "url": "https://m.tiktok.com/v/7047596209028074758.html?share_comment_id=7047599416228234031&share_item_id=7047596209028074758"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 393,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "7047599416228234031",
                          "url": "https://m.tiktok.com/v/7047596209028074758.html?share_comment_id=7047599416228234031&share_item_id=7047596209028074758"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokCommentResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Comment or reply with its likes and author",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.comment",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/comments": {
      "get": {
        "description": "Returns the public top-level comments on a TikTok video or photo post, a page at a time, in TikTok's own ranking. Each comment has its text, exact posting time, exact like and reply counts, the commenter's username, name, ID and verified badge, its language, and whether the creator pinned, liked or wrote it. Send a video or photo link, a share link or a numeric video ID.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Comment` items (the shared schema, the same on every platform), TikTok's comment ranking (the order its app shows). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/comments/ (Markdown: https://socialtap.dev/docs/reference/tiktok/comments/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/comments/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/comments/"
        },
        "operationId": "tiktok.comments.list",
        "parameters": [
          {
            "description": "TikTok video or photo post URL (tiktok.com/@user/video/<id>, /@user/photo/<id>, m.tiktok.com/v/<id>.html, embed and player URLs, vm.tiktok.com/<code>, vt.tiktok.com/<code>, tiktok.com/t/<code>) or a numeric video ID.",
            "example": "https://www.tiktok.com/@scout2015/video/6718335390845095173",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "TikTok video or photo post URL (tiktok.com/@user/video/<id>, /@user/photo/<id>, m.tiktok.com/v/<id>.html, embed and player URLs, vm.tiktok.com/<code>, vt.tiktok.com/<code>, tiktok.com/t/<code>) or a numeric video ID.",
              "examples": [
                "https://www.tiktok.com/@scout2015/video/6718335390845095173"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at, which is exact. TikTok ranks comments rather than ordering them by time, so this filters each page and never ends the walk by itself.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at, which is exact. TikTok ranks comments rather than ordering them by time, so this filters each page and never ends the walk by itself.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-alisg-avt-0068/8480bbf6854eaff6a4e31c974a1089c8~tplv-tiktokx-cropcenter:100:100.jpg?dr=9640&refresh_token=fb980cbc&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=30310797&shcp=ff37627b&idc=useast5",
                            "display_name": "paige",
                            "id": "57815654715637760",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@devilish.beans",
                            "username": "devilish.beans"
                          },
                          "edited_at": null,
                          "id": "6718948229226250245",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": false,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": 49,
                            "reply_count": 5
                          },
                          "parent_id": null,
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_sec_uid": "MS4wLjABAAAA9H4SK6VUa9XckL9ynvMU-HIaMgOQNnzrDoosLpyCwT3QzINE7ePngzQb5RRBnIGz",
                              "language": null,
                              "thread_id": null
                            }
                          },
                          "post_id": "6718335390845095173",
                          "published_at": "2019-07-29T05:10:43Z",
                          "text": "Guys people are guessing names it's on my username 😂",
                          "unknown_fields": [],
                          "url": "https://m.tiktok.com/v/6718335390845095173.html?share_comment_id=6718948229226250245&share_item_id=6718335390845095173"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/7331407432645509126~tplv-tiktokx-cropcenter:100:100.jpg?dr=9640&refresh_token=064ef873&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=30310797&shcp=ff37627b&idc=useast5",
                            "display_name": "vsco_room_xx",
                            "id": "6718326650415203333",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@vsco_room_xx",
                            "username": "vsco_room_xx"
                          },
                          "edited_at": null,
                          "id": "6722043930156417030",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": false,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": 53,
                            "reply_count": 44
                          },
                          "parent_id": null,
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_sec_uid": "MS4wLjABAAAArG6B4beBhFRzOVGzxvDgAKuz2yK0AHG9jfU6PiSjFoIPrtYEASAPir_quhWWPs-4",
                              "language": null,
                              "thread_id": null
                            }
                          },
                          "post_id": "6718335390845095173",
                          "published_at": "2019-08-06T13:23:37Z",
                          "text": "srii good luck",
                          "unknown_fields": [],
                          "url": "https://m.tiktok.com/v/6718335390845095173.html?share_comment_id=6722043930156417030&share_item_id=6718335390845095173"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/7328085019259748357~tplv-tiktokx-cropcenter:100:100.jpg?dr=9640&refresh_token=b7bb712c&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=30310797&shcp=ff37627b&idc=useast5",
                            "display_name": "Quit",
                            "id": "6627564337508761605",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@pretzelsticks0",
                            "username": "pretzelsticks0"
                          },
                          "edited_at": null,
                          "id": "6718336105873702917",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": true,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": 345,
                            "reply_count": 20
                          },
                          "parent_id": null,
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_sec_uid": "MS4wLjABAAAABCmZv8sEMzxVXCLVjoVUMYM465WA0BMplKB9c7y5WWXDpV0OykgbTV3qOf0Jbleg",
                              "language": null,
                              "thread_id": null
                            }
                          },
                          "post_id": "6718335390845095173",
                          "published_at": "2019-07-27T13:35:22Z",
                          "text": "Well it’s pretty easy...and obvious 😂 hlysa",
                          "unknown_fields": [],
                          "url": "https://m.tiktok.com/v/6718335390845095173.html?share_comment_id=6718336105873702917&share_item_id=6718335390845095173"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 436,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "6718335390845095173",
                          "url": "https://www.tiktok.com/@/video/6718335390845095173"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokCommentsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Top-level comments with exact like and reply counts",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.comments",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "TikTok's comment ranking (the order its app shows)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/download": {
      "get": {
        "description": "Returns direct, watermark-free download links for a public TikTok video or photo post, from its link, share link or numeric ID. You get every video rendition, best first, with its size, resolution, codec, bitrate and frame rate, every slideshow photo with its sound, the cover, and when each link expires. The links need no TikTok cookie.\n\nReturns `{data, meta}`: `data` is a `Download` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/download/ (Markdown: https://socialtap.dev/docs/reference/tiktok/download/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/download/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/download/"
        },
        "operationId": "tiktok.download.get",
        "parameters": [
          {
            "description": "TikTok video or photo post link (web, mobile, embed, player or share link) or a numeric post ID.",
            "example": "https://www.tiktok.com/@niinoclock/video/7673108027645414678?is_from_webapp=1&sender_device=pc",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "TikTok video or photo post link (web, mobile, embed, player or share link) or a numeric post ID.",
              "examples": [
                "https://www.tiktok.com/@niinoclock/video/7673108027645414678"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "published_at",
                          "duration_ms",
                          "files[].duration_ms"
                        ],
                        "author": {
                          "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/6fff7b147d5d98ee78f58331d80bbd93~tplv-tiktokx-cropcenter:100:100.jpeg?dr=9640&refresh_token=ab57b0a4&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                          "display_name": "Niina",
                          "id": null,
                          "is_verified": null,
                          "url": "https://www.tiktok.com/@niinoclock",
                          "username": "niinoclock"
                        },
                        "duration_ms": 495000,
                        "files": [
                          {
                            "audio_codec": "aac",
                            "bitrate_kbps": 707,
                            "duration_ms": 495000,
                            "expires_at": null,
                            "frame_rate": 56,
                            "height": 1920,
                            "is_video_only": false,
                            "is_watermarked": false,
                            "item_index": 0,
                            "mime_type": "video/mp4",
                            "size_bytes": 43793391,
                            "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-no1a-p-0037-no/oUy8yNAQEvDAfIJFF3DCBUWr9lBLjICeQ2ygfb~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=a70a8312&idc=useast5",
                            "type": "video",
                            "url": "https://www.tiktok.com/aweme/v1/play/?faid=1988&file_id=05419a9f22f241869a7d8f699fce95b3&is_play_url=1&item_id=7673108027645414678&line=0&ply_type=2&pt=dHQ0ZC5wbGF5ZXIuYXBpJi9wbGF5ZXIvYXBpL3YxL2l0ZW1zJjIwMjYxMTAxMjMxNzIxNTU4QjcyNjBERUUxRTUxRjE3OTImMTc5MzU3NTA0MSYxMDc3MjUzYTdmNjc&…",
                            "video_codec": "h265",
                            "width": 1080
                          },
                          {
                            "audio_codec": "aac",
                            "bitrate_kbps": 877,
                            "duration_ms": 495000,
                            "expires_at": null,
                            "frame_rate": 30,
                            "height": 1280,
                            "is_video_only": false,
                            "is_watermarked": false,
                            "item_index": 0,
                            "mime_type": "video/mp4",
                            "size_bytes": 54354244,
                            "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-no1a-p-0037-no/oUy8yNAQEvDAfIJFF3DCBUWr9lBLjICeQ2ygfb~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=a70a8312&idc=useast5",
                            "type": "video",
                            "url": "https://www.tiktok.com/aweme/v1/play/?faid=1988&file_id=e591b038bf824943831335499464cc8d&is_play_url=1&item_id=7673108027645414678&line=0&ply_type=2&pt=dHQ0ZC5wbGF5ZXIuYXBpJi9wbGF5ZXIvYXBpL3YxL2l0ZW1zJjIwMjYxMTAxMjMxNzIxNTU4QjcyNjBERUUxRTUxRjE3OTImMTc5MzU3NTA0MSYxMDc3MjUzYTdmNjc&…",
                            "video_codec": "h264",
                            "width": 720
                          },
                          {
                            "audio_codec": "aac",
                            "bitrate_kbps": 443,
                            "duration_ms": 495000,
                            "expires_at": null,
                            "frame_rate": 30,
                            "height": 1280,
                            "is_video_only": false,
                            "is_watermarked": false,
                            "item_index": 0,
                            "mime_type": "video/mp4",
                            "size_bytes": 27449177,
                            "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-no1a-p-0037-no/oUy8yNAQEvDAfIJFF3DCBUWr9lBLjICeQ2ygfb~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=a70a8312&idc=useast5",
                            "type": "video",
                            "url": "https://www.tiktok.com/aweme/v1/play/?faid=1988&file_id=ef73ad47ea274064b3f9aa901f63c9eb&is_play_url=1&item_id=7673108027645414678&line=0&ply_type=2&pt=dHQ0ZC5wbGF5ZXIuYXBpJi9wbGF5ZXIvYXBpL3YxL2l0ZW1zJjIwMjYxMTAxMjMxNzIxNTU4QjcyNjBERUUxRTUxRjE3OTImMTc5MzU3NTA0MSYxMDc3MjUzYTdmNjc&…",
                            "video_codec": "h265",
                            "width": 720
                          }
                        ],
                        "id": "7673108027645414678",
                        "platform": "tiktok",
                        "platform_specific": {
                          "tiktok": {
                            "is_download_allowed": null
                          }
                        },
                        "platform_type": "video",
                        "published_at": "2026-08-12T11:38:00Z",
                        "text": "Finally back with another Japanese meal tutorial! This time, I'm showing you how I make a Japanese cream stew 😋 Easy to make and arrange with different ingredients too! #japan #japanesefood #japantiktok #cookingtutorial #stew",
                        "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-no1a-p-0037-no/oUy8yNAQEvDAfIJFF3DCBUWr9lBLjICeQ2ygfb~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=a70a8312&idc=useast5",
                        "title": null,
                        "type": "video",
                        "unknown_fields": [],
                        "url": "https://www.tiktok.com/@niinoclock/video/7673108027645414678"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 466,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "7673108027645414678",
                          "url": "https://www.tiktok.com/@niinoclock/video/7673108027645414678"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokDownloadResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "no_media": {
                    "$ref": "#/components/examples/no_media"
                  },
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.\n\n`no_media`: The post exists but has no file to download: a text or link post, or one whose media the platform does not serve logged out. Do not retry. Fetch the post itself for its text and links.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Watermark-free video files and slideshow photos",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.download",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "download",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/effect": {
      "get": {
        "description": "Returns a TikTok camera effect or filter, TikTok's own or an Effect House creator's, from its link or ID. You get its name, icon and publish time, the creator's account (ID, handle, profile link, picture and secUid), and exact counts of the posts made with it and the views those posts drew.\n\nReturns `{data, meta}`: `data` is a `Effect` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/effect/ (Markdown: https://socialtap.dev/docs/reference/tiktok/effect/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/effect/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/effect/"
        },
        "operationId": "tiktok.effect.get",
        "parameters": [
          {
            "description": "A TikTok effect link (the effect page's tiktok.com/effect/Bold-Glamour-14519845, or the older tiktok.com/sticker/Bold-Glamour-14519845) or the effect's numeric ID (the number at the end of that link). Short share links (vm.tiktok.com/…) are not accepted: open one and send the link it lands on.",
            "example": "https://www.tiktok.com/effect/Bold-Glamour-14519845",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "A TikTok effect link (the effect page's tiktok.com/effect/Bold-Glamour-14519845, or the older tiktok.com/sticker/Bold-Glamour-14519845) or the effect's numeric ID (the number at the end of that link). Short share links (vm.tiktok.com/…) are not accepted: open one and send the link it lands on.",
              "examples": [
                "https://www.tiktok.com/effect/Bold-Glamour-14519845"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "creator": {
                          "avatar_url": null,
                          "display_name": "Effect Assistant",
                          "id": null,
                          "is_verified": null,
                          "url": null,
                          "username": null
                        },
                        "description": null,
                        "icon_url": "https://lf16-effectcdn-us.tiktokcdn-us.com/obj/tiktok-loki-effect-oracle-tx/4712bb553f7a528d9e6ffeef6d943e82",
                        "id": "14519845",
                        "is_official": true,
                        "media": [],
                        "metrics": {
                          "post_count": 304524339,
                          "total_view_count": 72079393008
                        },
                        "name": "Bold Glamour",
                        "platform": "tiktok",
                        "platform_specific": {
                          "tiktok": {
                            "creator_sec_uid": null
                          }
                        },
                        "published_at": "2023-02-24T10:32:30Z",
                        "unknown_fields": [
                          "media"
                        ],
                        "url": "https://www.tiktok.com/effect/-14519845"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 271,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "effect",
                          "id": "14519845",
                          "url": "https://www.tiktok.com/effect/-14519845"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokEffectResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Effect or filter with exact post and view counts",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.effect",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "effect",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/effect_posts": {
      "get": {
        "description": "Returns the public TikTok videos and photo posts made with a camera effect, a page at a time, from the effect's link or ID. Each has its caption, hashtags, publish time, exact duration, cover, a playable video link, author, sound, and exact view, like, comment, share and save counts.\n\nReturns `{data, page, meta}`: `data` holds up to 30 `Post` items (the shared schema, the same on every platform), TikTok's ranking of the effect's posts (the order its effect page shows). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/effect_posts/ (Markdown: https://socialtap.dev/docs/reference/tiktok/effect_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/effect_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/effect_posts/"
        },
        "operationId": "tiktok.effect_posts.list",
        "parameters": [
          {
            "description": "A TikTok effect link (the effect page's tiktok.com/effect/Bold-Glamour-14519845, or the older tiktok.com/sticker/Bold-Glamour-14519845) or the effect's numeric ID (the number at the end of that link). Short share links (vm.tiktok.com/…) are not accepted: open one and send the link it lands on.",
            "example": "https://www.tiktok.com/effect/Bold-Glamour-14519845",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "A TikTok effect link (the effect page's tiktok.com/effect/Bold-Glamour-14519845, or the older tiktok.com/sticker/Bold-Glamour-14519845) or the effect's numeric ID (the number at the end of that link). Short share links (vm.tiktok.com/…) are not accepted: open one and send the link it lands on.",
              "examples": [
                "https://www.tiktok.com/effect/Bold-Glamour-14519845"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 30,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 30,
              "maximum": 30,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/7320421731494002731~tplv-tiktokx-cropcenter:1080:1080.webp?dr=9640&refresh_token=9fb840f2&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=d05b14bd&shcp=34ff8df6&idc=useast5",
                            "display_name": "Chris Hall",
                            "id": "7137831667897566251",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@chrizzhall",
                            "username": "chrizzhall"
                          },
                          "coauthors": [],
                          "duration_ms": 13443,
                          "hashtags": [
                            "fyp",
                            "foryou",
                            "viral"
                          ],
                          "id": "7271010959592836394",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 13443,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1280,
                              "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/oIKB5AbBkzgDEoj3IeAxQ18DI0exyJPfn1H6CB~tplv-tiktokx-cropcenter:300:400.jpeg?dr=9640&refresh_token=7ef52333&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=d05b14bd&shcp=34ff8df6&idc=useast5&s=STIC…",
                              "type": "video",
                              "url": "https://v16m-default.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast5/tos-useast5-ve-0068c002-tx/oE0c4egIDorQAoz66nbKiCeAjfgXJnk4HgtgCm/?a=1988&bti=O0BzNjQ6QGo6OjZALnAjLzYzYCMxNDNg&&bt=910&ft=TkDc21qVv9jQ9RBXx3QVH.C2pnloZcAkgwF35H6KJE&mime_type=video_mp4&rc=OmZnOGg8aWlmZDQ0Z2…",
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 83556,
                            "like_count": 8122548,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 755185,
                            "share_count": 1081828,
                            "view_count": 78925127
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAj46K3iTPrbhVFOYhHIoQTxO6TceYceoPxmKmlSUZ-6wWVG1IsDFd8shiTkabvlFl",
                              "board": null,
                              "country_code": "US",
                              "is_ad": false,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "MareeStudio",
                                "cover_url": "https://p19-common-sign.tiktokcdn-us.com/tos-alisg-avt-0068/781317f788392dfa7c0ecd38f3c3d557~tplv-tiktokx-cropcenter:1080:1080.webp?dr=9640&refresh_token=43b383ee&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=d05b14bd&shcp=34ff8df6&idc=useast5",
                                "duration_ms": 13401,
                                "id": "7260815243714284294",
                                "is_original": true,
                                "play_url": null,
                                "title": "original sound - noomaree17"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2023-08-24T21:56:14Z",
                          "text": "not a thought behind those eyes #fyp#foryou#viral#trending#chrizzhall",
                          "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/oIKB5AbBkzgDEoj3IeAxQ18DI0exyJPfn1H6CB~tplv-tiktokx-cropcenter:300:400.jpeg?dr=9640&refresh_token=7ef52333&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=d05b14bd&shcp=34ff8df6&idc=useast5&s=STIC…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@chrizzhall/video/7271010959592836394"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/fc741e32073c045c24a2f96cec4d7c80~tplv-tiktokx-cropcenter:1080:1080.webp?dr=9640&refresh_token=fe4bafcb&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=d05b14bd&shcp=34ff8df6&idc=useast5",
                            "display_name": "Janice🌺",
                            "id": "3768450",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@janicee.janicee",
                            "username": "janicee.janicee"
                          },
                          "coauthors": [],
                          "duration_ms": 8451,
                          "hashtags": [],
                          "id": "7234650135660072235",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 8451,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1280,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/f47b8593553e48eaa62fb21bcf51862a~tplv-tiktokx-cropcenter:300:400.jpeg?dr=9640&refresh_token=b16c4bb2&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=d05b14bd&shcp=34ff8df6&idc=useast5&s=STICKER_AW…",
                              "type": "video",
                              "url": "https://v16m-default.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast5/tos-useast5-ve-0068c002-tx/oUrHNaIUmfePsC0pA8kDU2Hc4IAjZQzqYrfJBI/?a=1988&bti=O0BzNjQ6QGo6OjZALnAjLzYzYCMxNDNg&&bt=1172&ft=TkDc21qVv9jQ9RBXx3QVH.C2pnloZcAkgwF35H6KJE&mime_type=video_mp4&rc=NjxkODg0ZjtlNTZmZ…",
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 10576,
                            "like_count": 5088417,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 320511,
                            "share_count": 98199,
                            "view_count": 36241774
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAAFW6XU8AFpMkgwufL7EJTuvUbuhW5l2pWFaV074Ob78",
                              "board": null,
                              "country_code": "US",
                              "is_ad": false,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": null,
                                "cover_url": null,
                                "duration_ms": null,
                                "id": "7218301459312413442",
                                "is_original": false,
                                "play_url": null,
                                "title": null
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2023-05-18T22:17:35Z",
                          "text": null,
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/f47b8593553e48eaa62fb21bcf51862a~tplv-tiktokx-cropcenter:300:400.jpeg?dr=9640&refresh_token=b16c4bb2&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=d05b14bd&shcp=34ff8df6&idc=useast5&s=STICKER_AW…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@janicee.janicee/video/7234650135660072235"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/55845ae46b5795037333329e85173291~tplv-tiktokx-cropcenter:1080:1080.webp?dr=9640&refresh_token=9c3f98c3&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=d05b14bd&shcp=34ff8df6&idc=useast5",
                            "display_name": "Victoria :)",
                            "id": "4998232",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@victoria.rozmajzl",
                            "username": "victoria.rozmajzl"
                          },
                          "coauthors": [],
                          "duration_ms": 8265,
                          "hashtags": [],
                          "id": "7221237204662619435",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 8265,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1280,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/14a0a81d6d52409ab6360734d1e3e088_1681325313~tplv-tiktokx-cropcenter:300:400.jpeg?dr=9640&refresh_token=17dbfd51&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=d05b14bd&shcp=34ff8df6&idc=useast5&s…",
                              "type": "video",
                              "url": "https://v16m-default.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast5/tos-useast5-pve-0068-tx/osndeDbDIgNUkYqSGoBnRuAL1hQW8vEdn05vft/?a=1988&bti=O0BzNjQ6QGo6OjZALnAjLzYzYCMxNDNg&&bt=924&ft=TkDc21qVv9jQ9RBXx3QVH.C2pnloZcAkgwF35H6KJE&mime_type=video_mp4&rc=MzNkZ2U1OzM4Mzo6ZTVpO…",
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 23208,
                            "like_count": 5045584,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 262025,
                            "share_count": 331700,
                            "view_count": 24137284
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAA98dmZ3wsCI5XjkcGy-pbPAiwe2jlVqLBcbe1Bc1MiwI",
                              "board": null,
                              "country_code": "US",
                              "is_ad": false,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "SUZY SANTOS",
                                "cover_url": "https://p16-common-sign.tiktokcdn-us.com/tos-alisg-avt-0068/6311f2b0cf7913c9c09d15bf3dc8dc3d~tplv-tiktokx-cropcenter:1080:1080.webp?dr=9640&refresh_token=97e9f4c1&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=d05b14bd&shcp=34ff8df6&idc=useast5",
                                "duration_ms": 34299,
                                "id": "7082409164084988677",
                                "is_original": true,
                                "play_url": null,
                                "title": "original sound - suz1sant0s"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2023-04-12T18:48:32Z",
                          "text": null,
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/14a0a81d6d52409ab6360734d1e3e088_1681325313~tplv-tiktokx-cropcenter:300:400.jpeg?dr=9640&refresh_token=17dbfd51&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=d05b14bd&shcp=34ff8df6&idc=useast5&s…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@victoria.rozmajzl/video/7221237204662619435"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 647,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "effect",
                          "id": "14519845",
                          "url": "https://www.tiktok.com/effect/-14519845"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokEffect_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Videos and photo posts made with an effect",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.effect_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "TikTok's ranking of the effect's posts (the order its effect page shows)",
          "page_max": 30,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/engagement": {
      "get": {
        "description": "Returns a public TikTok account's engagement rate and post analytics, computed over its latest posts, in one request. You get the profile, its latest videos and photo posts, and the figures over them: engagement rate per follower and per view (mean, median and spread), average views, likes, comments, shares and saves, median views, comment-to-like ratio, posting cadence, the video and photo mix, and the top and bottom post with how each compares with a typical post. Send a username, profile link or user ID.\n\nReturns `{data, meta}`: `data` is a `Engagement` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/engagement/ (Markdown: https://socialtap.dev/docs/reference/tiktok/engagement/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/engagement/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/engagement/"
        },
        "operationId": "tiktok.engagement.get",
        "parameters": [
          {
            "description": "TikTok username with or without the @ (nasa, @nasa), a profile URL (tiktok.com/@nasa), or a numeric user ID (tiktok.com/share/user/<id> or the bare ID). Usernames are case-insensitive.",
            "example": "nasa",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "TikTok username with or without the @ (nasa, @nasa), a profile URL (tiktok.com/@nasa), or a numeric user ID (tiktok.com/share/user/<id> or the bare ID). Usernames are case-insensitive.",
              "examples": [
                "nasa"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "metrics.views_per_post",
                          "metrics.median_views_per_post",
                          "metrics.likes_per_post"
                        ],
                        "bottom_post_id": "7689547576265149710",
                        "id": "7664638705177150477",
                        "metrics": {
                          "comment_to_like_ratio": 0.019003,
                          "comments_per_post": 694.33,
                          "counted_post_count": 15,
                          "engagement_rate": 0.017295,
                          "engagement_rate_stddev": 0.022116,
                          "formats": [
                            {
                              "counted_post_count": 14,
                              "engagement_rate": 0.018117,
                              "interactions_per_post": 39001.14,
                              "type": "video",
                              "views_per_post": 482564.29
                            },
                            {
                              "counted_post_count": 1,
                              "engagement_rate": 0.005787,
                              "interactions_per_post": 12459,
                              "type": "carousel",
                              "views_per_post": 113600
                            }
                          ],
                          "interactions_per_post": 37231.67,
                          "likes_per_post": 36537.33,
                          "median_engagement_rate": 0.005787,
                          "median_views_per_post": 292900,
                          "posts_per_week": 2.81,
                          "quotes_per_post": null,
                          "rated_post_count": 15,
                          "reposts_per_post": null,
                          "sampled_post_count": 15,
                          "saves_per_post": 2554.8,
                          "shares_per_post": 1096,
                          "view_engagement_rate": 0.071422,
                          "views_per_post": 457966.67
                        },
                        "newest_post_at": "2026-10-30T16:52:44Z",
                        "oldest_post_at": "2026-09-25T18:52:22Z",
                        "platform": "tiktok",
                        "platform_specific": {},
                        "posts": [
                          {
                            "engagement_rate": 0.004453,
                            "engagement_vs_median": 0.77,
                            "is_counted": true,
                            "post": {
                              "approximate_fields": [
                                "metrics.view_count"
                              ],
                              "author": {
                                "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/e5143212a59c09a008bf50f487d54d1f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=1e9c8bc8&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "display_name": "NASA",
                                "id": "7664638705177150477",
                                "is_verified": true,
                                "url": "https://www.tiktok.com/@nasa",
                                "username": "nasa"
                              },
                              "coauthors": [],
                              "duration_ms": 108000,
                              "hashtags": [],
                              "id": "7702504724049743117",
                              "is_nsfw": null,
                              "is_pinned": null,
                              "is_sponsored": null,
                              "language": "en",
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": 108000,
                                  "expires_at": null,
                                  "height": 1280,
                                  "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/o8e3EAJERS9f6tHYlgAMTQA5IAHqg8Dy6arDFC~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                                  "type": "video",
                                  "url": null,
                                  "width": 720
                                }
                              ],
                              "mentions": [],
                              "metrics": {
                                "comment_count": 228,
                                "like_count": 9359,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": 1149,
                                "share_count": 339,
                                "view_count": 87300
                              },
                              "platform": "tiktok",
                              "platform_specific": {
                                "tiktok": {
                                  "author_follower_count": null,
                                  "author_sec_uid": "MS4wLjABAAAAU9BRVzC8oCaegVnia8IbqWhPb_-dbU7s00Y3wS1_Nx8g5RUaYvyXrpejgjdxTwd6",
                                  "board": null,
                                  "country_code": null,
                                  "is_ad": false,
                                  "is_ai_generated": false,
                                  "location": null,
                                  "music": {
                                    "author_name": "NASA",
                                    "cover_url": "https://p16-common.tiktokcdn-us.com/tos-useast5-avt-0068-tx/e5143212a59c09a008bf50f487d54d1f~tplv-tiktokx-cropcenter:720:720.jpeg?dr=9584&t=4d5b0474&ps=933b5bde&shp=08d74b56&shcp=81f88b70&idc=useast5",
                                    "duration_ms": 108000,
                                    "id": "7702504816472640270",
                                    "is_original": false,
                                    "play_url": "https://v16-webapp-prime.us.tiktok.com/video/tos/useast5/tos-useast5-v-27dcd7-tx/ooFa1AQVyE3nHYfAEekZDTyCk8kfE2OAoXiAED/?a=1988&bti=ODszNWYuMDE6&&bt=125&ft=GcAInInz7ThretyGXq8Zmo&mime_type=audio_mpeg&rc=M3J0c3g5cnFmZTMzZzU8NEBpM3J0c3g5cnFmZTMzZzU8NEBlYi5fMmRzamZhLS1kMS9zYSNlYi5fM…",
                                    "title": "original sound - NASA"
                                  }
                                }
                              },
                              "platform_type": "video",
                              "published_at": "2026-10-30T16:52:44Z",
                              "text": "Another week of building, flying, and looking ahead at NASA 🚀 🌔 Artemis III core stage integrated 🛰️ New solar array installed on the ISS 🪐 Send your name to Titan aboard Dragonfly ✈️ MAX POWER heads to Kennedy Space Center next week Here’s your NASA Minute!",
                              "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/o8e3EAJERS9f6tHYlgAMTQA5IAHqg8Dy6arDFC~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "title": null,
                              "type": "video",
                              "unknown_fields": [],
                              "url": "https://www.tiktok.com/@nasa/video/7702504724049743117"
                            },
                            "view_engagement_rate": 0.109817,
                            "views_vs_median": 0.3
                          },
                          {
                            "engagement_rate": 0.005787,
                            "engagement_vs_median": 1,
                            "is_counted": true,
                            "post": {
                              "approximate_fields": [
                                "metrics.view_count",
                                "metrics.like_count"
                              ],
                              "author": {
                                "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/e5143212a59c09a008bf50f487d54d1f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=1e9c8bc8&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "display_name": "NASA",
                                "id": "7664638705177150477",
                                "is_verified": true,
                                "url": "https://www.tiktok.com/@nasa",
                                "username": "nasa"
                              },
                              "coauthors": [],
                              "duration_ms": null,
                              "hashtags": [],
                              "id": "7701866987609197837",
                              "is_nsfw": null,
                              "is_pinned": null,
                              "is_sponsored": null,
                              "language": "en",
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": 1508,
                                  "thumbnail_url": null,
                                  "type": "image",
                                  "url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-i-photomode-tx/37715b80324f4d9b83ccbdc1694240dd~tplv-photomode-image.jpeg?dr=9616&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=9b759fb9&idc=useast5&ftpl=1",
                                  "width": 1206
                                },
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": 1508,
                                  "thumbnail_url": null,
                                  "type": "image",
                                  "url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-i-photomode-tx/bb26d224aae14211815a7ba68046275d~tplv-photomode-image.jpeg?dr=9616&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=9b759fb9&idc=useast5&ftpl=1",
                                  "width": 1206
                                },
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": 1608,
                                  "thumbnail_url": null,
                                  "type": "image",
                                  "url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-i-photomode-tx/7776ea0097594238a9b5a8517b48a635~tplv-photomode-image.jpeg?dr=9616&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=9b759fb9&idc=useast5&ftpl=1",
                                  "width": 1206
                                }
                              ],
                              "mentions": [],
                              "metrics": {
                                "comment_count": 359,
                                "like_count": 12100,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": 1254,
                                "share_count": 587,
                                "view_count": 113600
                              },
                              "platform": "tiktok",
                              "platform_specific": {
                                "tiktok": {
                                  "author_follower_count": null,
                                  "author_sec_uid": "MS4wLjABAAAAU9BRVzC8oCaegVnia8IbqWhPb_-dbU7s00Y3wS1_Nx8g5RUaYvyXrpejgjdxTwd6",
                                  "board": null,
                                  "country_code": null,
                                  "is_ad": false,
                                  "is_ai_generated": false,
                                  "location": null,
                                  "music": {
                                    "author_name": "DRYVE",
                                    "cover_url": "https://p16-common.tiktokcdn-us.com/tos-alisg-v-2774/oYeEG4NJrWGsMZjIHfLfjQAfMUApQAKyfHAAAV~tplv-tiktokx-cropcenter:720:720.jpeg?dr=9584&t=4d5b0474&ps=933b5bde&shp=08d74b56&shcp=81f88b70&idc=useast5",
                                    "duration_ms": 60000,
                                    "id": "6818255658807216129",
                                    "is_original": false,
                                    "play_url": "https://sf19.tiktokcdn-us.com/obj/tos-alisg-ve-2774/osWGyxQwgMAEzas8kfXAZuZUEffetrVbMKfN7u",
                                    "title": "City Nights - Instrumental"
                                  }
                                }
                              },
                              "platform_type": "photo",
                              "published_at": "2026-10-28T23:37:45Z",
                              "text": "The core stage of our Artemis III rocket is officially stacked! Teams at NASA Kennedy lifted and positioned the 212-foot stage between its two solid rocket boosters, bringing the mission another step closer to launch. Artemis III will test how Orion and commercial lunar landers m…",
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-i-photomode-tx/b20cf730de5c4ccaabdb7301ab3ff57a~tplv-photomode-image.jpeg?dr=9616&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=9b759fb9&idc=useast5&ftpl=1",
                              "title": "Some assembly required 🚀",
                              "type": "carousel",
                              "unknown_fields": [],
                              "url": "https://www.tiktok.com/@nasa/photo/7701866987609197837"
                            },
                            "view_engagement_rate": 0.109674,
                            "views_vs_median": 0.39
                          },
                          {
                            "engagement_rate": 0.003835,
                            "engagement_vs_median": 0.66,
                            "is_counted": true,
                            "post": {
                              "approximate_fields": [
                                "metrics.view_count"
                              ],
                              "author": {
                                "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/e5143212a59c09a008bf50f487d54d1f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=1e9c8bc8&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "display_name": "NASA",
                                "id": "7664638705177150477",
                                "is_verified": true,
                                "url": "https://www.tiktok.com/@nasa",
                                "username": "nasa"
                              },
                              "coauthors": [],
                              "duration_ms": 16000,
                              "hashtags": [],
                              "id": "7700397098994273549",
                              "is_nsfw": null,
                              "is_pinned": null,
                              "is_sponsored": null,
                              "language": "en",
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": 16000,
                                  "expires_at": null,
                                  "height": 1280,
                                  "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/ocaE0AdEmkIUAaBg8jiTDyiOA1AAdrBC4vrBt~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                                  "type": "video",
                                  "url": null,
                                  "width": 720
                                }
                              ],
                              "mentions": [],
                              "metrics": {
                                "comment_count": 254,
                                "like_count": 8002,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": 509,
                                "share_count": 241,
                                "view_count": 126700
                              },
                              "platform": "tiktok",
                              "platform_specific": {
                                "tiktok": {
                                  "author_follower_count": null,
                                  "author_sec_uid": "MS4wLjABAAAAU9BRVzC8oCaegVnia8IbqWhPb_-dbU7s00Y3wS1_Nx8g5RUaYvyXrpejgjdxTwd6",
                                  "board": null,
                                  "country_code": null,
                                  "is_ad": false,
                                  "is_ai_generated": false,
                                  "location": null,
                                  "music": {
                                    "author_name": "NASA",
                                    "cover_url": "https://p16-common.tiktokcdn-us.com/tos-useast5-avt-0068-tx/e5143212a59c09a008bf50f487d54d1f~tplv-tiktokx-cropcenter:720:720.jpeg?dr=9584&t=4d5b0474&ps=933b5bde&shp=08d74b56&shcp=81f88b70&idc=useast5",
                                    "duration_ms": 16000,
                                    "id": "7700397137514793741",
                                    "is_original": false,
                                    "play_url": "https://v16-webapp-prime.us.tiktok.com/video/tos/useast5/tos-useast5-v-27dcd7-tx/oICbTAGnuGpezA8s6jeWkydIAofLIoVMHIAENs/?a=1988&bti=ODszNWYuMDE6&&bt=125&ft=GcAInInz7ThretyGXq8Zmo&mime_type=audio_mpeg&rc=M3BydHk5cnVuZTMzZzU8NEBpM3BydHk5cnVuZTMzZzU8NEBeYG5sMmRrcGJhLS1kMS9zYSNeYG5sM…",
                                    "title": "original sound - NASA"
                                  }
                                }
                              },
                              "platform_type": "video",
                              "published_at": "2026-10-25T00:33:47Z",
                              "text": "NASA 🤝 college football. We heard y’all like a good air show. Roll Tide!",
                              "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/ocaE0AdEmkIUAaBg8jiTDyiOA1AAdrBC4vrBt~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "title": null,
                              "type": "video",
                              "unknown_fields": [],
                              "url": "https://www.tiktok.com/@nasa/video/7700397098994273549"
                            },
                            "view_engagement_rate": 0.065162,
                            "views_vs_median": 0.43
                          }
                        ],
                        "profile": {
                          "approximate_fields": [],
                          "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/e5143212a59c09a008bf50f487d54d1f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=1e9c8bc8&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                          "banner_url": null,
                          "bio": "Making the seemingly impossible, possible.✨",
                          "category": null,
                          "country_code": null,
                          "created_at": "2026-07-20T15:55:49Z",
                          "display_name": "NASA",
                          "external_links": [
                            {
                              "title": null,
                              "url": "https://science.nasa.gov/feature/artemis-ii-preliminary-lunar-science-report"
                            }
                          ],
                          "id": "7664638705177150477",
                          "is_private": false,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": 2152752,
                            "following_count": 23,
                            "post_count": 62,
                            "total_like_count": 11486135,
                            "total_view_count": null
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "display_name_changed_at": null,
                              "friend_count": null,
                              "is_business_account": false,
                              "is_shop_seller": null,
                              "language": null,
                              "liked_post_count": null,
                              "sec_uid": null
                            }
                          },
                          "type": "organization",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@nasa",
                          "username": "nasa"
                        },
                        "top_post_id": "7691683140015820046",
                        "unknown_fields": [],
                        "url": "https://www.tiktok.com/@nasa"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1655,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "7664638705177150477",
                          "url": "https://www.tiktok.com/@nasa"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokEngagementResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Engagement rate, views per post and posting cadence",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.engagement",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "engagement",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/followers": {
      "get": {
        "description": "Returns the accounts that follow a public TikTok account, newest follower first, from a username, profile link, user ID or secUid. Each follower comes with its username, display name, bio, avatar, verified and private flags, secUid, and exact follower, following, like and video counts. Page through the list with the cursor.\n\nReturns `{data, page, meta}`: `data` holds up to 30 `Profile` items (the shared schema, the same on every platform), newest follower first (most recently followed). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/followers/ (Markdown: https://socialtap.dev/docs/reference/tiktok/followers/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/followers/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/followers/"
        },
        "operationId": "tiktok.followers.list",
        "parameters": [
          {
            "description": "TikTok username with or without the @, a profile URL (tiktok.com/@nasa), a numeric user ID or a secUid (MS4wLjABAAAA…).",
            "example": "nasa",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "TikTok username with or without the @, a profile URL (tiktok.com/@nasa), a numeric user ID or a secUid (MS4wLjABAAAA…).",
              "examples": [
                "nasa"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 30,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 30,
              "maximum": 30,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-alisg-avt-0068/d6b6d3be341ea27bfb8d950ac0ee91ce~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=5bbe37d9&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                          "banner_url": null,
                          "bio": "Al chile las mejores ias son meta y chatgpt",
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "al_chile_metaxdddd",
                          "external_links": [],
                          "id": "7689250766540194868",
                          "is_private": false,
                          "is_verified": false,
                          "location": null,
                          "metrics": {
                            "follower_count": 29,
                            "following_count": 490,
                            "post_count": 16,
                            "total_like_count": 139,
                            "total_view_count": null
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "display_name_changed_at": null,
                              "friend_count": null,
                              "is_business_account": null,
                              "is_shop_seller": false,
                              "language": null,
                              "liked_post_count": null,
                              "sec_uid": "MS4wLjABAAAAlH7YzCU4eWWiXWBQ3ye4ZFZW64HrIVbz6n94ddUADALOXsI-kvkr_BiWXBZSMOty"
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links"
                          ],
                          "url": "https://www.tiktok.com/@good230vx1",
                          "username": "good230vx1"
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/b84aa5b3cae71459284abc4939ca1f5d~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=db2c5d9f&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "MONSE",
                          "external_links": [],
                          "id": "7189067638521775109",
                          "is_private": true,
                          "is_verified": false,
                          "location": null,
                          "metrics": {
                            "follower_count": 113,
                            "following_count": 167,
                            "post_count": 0,
                            "total_like_count": 1,
                            "total_view_count": null
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "display_name_changed_at": null,
                              "friend_count": null,
                              "is_business_account": null,
                              "is_shop_seller": false,
                              "language": null,
                              "liked_post_count": null,
                              "sec_uid": "MS4wLjABAAAAT56Zpm2zHV1oa_psVKqicN5PNU6pHmc88K9w-ETRF1f6t5oRpm5efZsvFN0RrLc8"
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links"
                          ],
                          "url": "https://www.tiktok.com/@lit.monse_",
                          "username": "lit.monse_"
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast2a-avt-0068-euttp/c063429352eebb4ba94d3a24fbb4a6b3~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=12cbb3bc&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                          "banner_url": null,
                          "bio": "Hello",
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "Charles-Valentin Morhange",
                          "external_links": [],
                          "id": "7455535115968594966",
                          "is_private": false,
                          "is_verified": false,
                          "location": null,
                          "metrics": {
                            "follower_count": 284,
                            "following_count": 609,
                            "post_count": 37,
                            "total_like_count": 4780,
                            "total_view_count": null
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "display_name_changed_at": null,
                              "friend_count": null,
                              "is_business_account": null,
                              "is_shop_seller": false,
                              "language": null,
                              "liked_post_count": null,
                              "sec_uid": "MS4wLjABAAAARKXKRLyDoe11zLShjMTz35TyuW5ai-sfhnIOlj8v5a3bz6sKHRXdjODmIZdWvc4Y"
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links"
                          ],
                          "url": "https://www.tiktok.com/@imanalkanist",
                          "username": "imanalkanist"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "7664638705177150477",
                          "url": "https://www.tiktok.com/@nasa"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokFollowersResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Followers of an account with exact counts, newest first",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.followers",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest follower first (most recently followed)",
          "page_max": 30,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/following": {
      "get": {
        "description": "Returns the accounts a public TikTok account follows, most recently followed first, from a username, profile link, user ID or secUid. Each account comes with its username, display name, bio, avatar, verified and private flags, secUid, and exact follower, following, like and video counts. Page through the list with the cursor.\n\nReturns `{data, page, meta}`: `data` holds up to 30 `Profile` items (the shared schema, the same on every platform), most recently followed first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/following/ (Markdown: https://socialtap.dev/docs/reference/tiktok/following/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/following/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/following/"
        },
        "operationId": "tiktok.following.list",
        "parameters": [
          {
            "description": "TikTok username with or without the @, a profile URL (tiktok.com/@nasa), a numeric user ID or a secUid (MS4wLjABAAAA…).",
            "example": "khaby.lame",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "TikTok username with or without the @, a profile URL (tiktok.com/@nasa), a numeric user ID or a secUid (MS4wLjABAAAA…).",
              "examples": [
                "nasa"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 30,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 30,
              "maximum": 30,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/5f78661ab7569a41cae5e990d2316eee~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=1ed539ac&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                          "banner_url": null,
                          "bio": "Email: business@xeviuniverse.com\nPodcast ⬇️",
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "Xevi",
                          "external_links": [],
                          "id": "6769661547985847302",
                          "is_private": false,
                          "is_verified": false,
                          "location": null,
                          "metrics": {
                            "follower_count": 5336993,
                            "following_count": 245,
                            "post_count": 1165,
                            "total_like_count": 241913385,
                            "total_view_count": null
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "display_name_changed_at": null,
                              "friend_count": null,
                              "is_business_account": null,
                              "is_shop_seller": false,
                              "language": null,
                              "liked_post_count": null,
                              "sec_uid": "MS4wLjABAAAAFQ1MMGr1Up7yqeOGwW2icV4-OS0VP5uRcoKmY9QVGbXwDcyTXHpmpVJqdMpRXT24"
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links"
                          ],
                          "url": "https://www.tiktok.com/@xeviuniverse",
                          "username": "xeviuniverse"
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/aa6a4e62bf2da5dca3593b5a0e5e476f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=5e5b7775&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                          "banner_url": null,
                          "bio": null,
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "user38180545530128",
                          "external_links": [],
                          "id": "7530943790661305399",
                          "is_private": false,
                          "is_verified": false,
                          "location": null,
                          "metrics": {
                            "follower_count": 12925,
                            "following_count": 0,
                            "post_count": 279,
                            "total_like_count": 84577,
                            "total_view_count": null
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "display_name_changed_at": null,
                              "friend_count": null,
                              "is_business_account": null,
                              "is_shop_seller": false,
                              "language": null,
                              "liked_post_count": null,
                              "sec_uid": "MS4wLjABAAAAK7CNRYoImyzWUgPu9lbLy4whAuyIg5fcKd9sG3Sr8dL5-2xwIE1kmm6Tq6b5zKkf"
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links"
                          ],
                          "url": "https://www.tiktok.com/@user38180545530128",
                          "username": "user38180545530128"
                        },
                        {
                          "approximate_fields": [],
                          "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast2a-avt-0068-euttp/d260685754e3ae8139f47e7ec9fda7e9~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=0914a1e0&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                          "banner_url": null,
                          "bio": "🏆 The official #FIFAWorldCup account on TikTok",
                          "category": null,
                          "country_code": null,
                          "created_at": null,
                          "display_name": "FIFA World Cup",
                          "external_links": [],
                          "id": "7059636734342038534",
                          "is_private": false,
                          "is_verified": true,
                          "location": null,
                          "metrics": {
                            "follower_count": 84168308,
                            "following_count": 93,
                            "post_count": 11388,
                            "total_like_count": 3308612098,
                            "total_view_count": null
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "display_name_changed_at": null,
                              "friend_count": null,
                              "is_business_account": null,
                              "is_shop_seller": false,
                              "language": null,
                              "liked_post_count": null,
                              "sec_uid": "MS4wLjABAAAApf8MKCE246Q60LYymhpec5wPGF-uaGZgzl7W19U-AxtzHzeydNdE8xZedO_gUWDL"
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [
                            "external_links"
                          ],
                          "url": "https://www.tiktok.com/@fifaworldcup",
                          "username": "fifaworldcup"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "127905465618821121",
                          "url": "https://www.tiktok.com/@khaby.lame"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokFollowingResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Accounts an account follows, with exact counts",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.following",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "most recently followed first",
          "page_max": 30,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/hashtag": {
      "get": {
        "description": "Returns a TikTok hashtag with its exact post and view counts, from its link, its name (with or without the #) or its ID. You also get TikTok's challenge ID, page link, description, picture and banner, and whether it is an advertiser's Branded Hashtag Challenge.\n\nReturns `{data, meta}`: `data` is a `Hashtag` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/hashtag/ (Markdown: https://socialtap.dev/docs/reference/tiktok/hashtag/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/hashtag/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/hashtag/"
        },
        "operationId": "tiktok.hashtag.get",
        "parameters": [
          {
            "description": "A TikTok hashtag page link (tiktok.com/tag/cooking), the hashtag itself with or without the # (cooking, #cooking), or the app's share link of a hashtag by its ID (m.tiktok.com/h5/share/tag/18973.html). Hashtags are case-insensitive and may be in any script (#美食); an all-digit hashtag (#2024) is read as a name, not an ID. A short link (vm.tiktok.com/…, tiktok.com/t/…) is not read: open it and send the link it lands on.",
            "example": "https://www.tiktok.com/tag/cooking",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "A TikTok hashtag page link (tiktok.com/tag/cooking), the hashtag itself with or without the # (cooking, #cooking), or the app's share link of a hashtag by its ID (m.tiktok.com/h5/share/tag/18973.html). Hashtags are case-insensitive and may be in any script (#美食); an all-digit hashtag (#2024) is read as a name, not an ID. A short link (vm.tiktok.com/…, tiktok.com/t/…) is not read: open it and send the link it lands on.",
              "examples": [
                "https://www.tiktok.com/tag/cooking"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "description": null,
                        "id": "18973",
                        "metrics": {
                          "post_count": 19505055
                        },
                        "name": "cooking",
                        "platform": "tiktok",
                        "platform_specific": {
                          "tiktok": {
                            "banner_url": null,
                            "industry": null,
                            "is_new_to_board": null,
                            "is_promoted": false,
                            "period_post_count": null,
                            "period_view_count": null,
                            "rank": null,
                            "rank_change": null,
                            "trend": [],
                            "view_count": 560541308708
                          }
                        },
                        "thumbnail_url": "https://p16-common-sign.tiktokcdn.com/musically-maliva-obj/bbbcb935f04337b7e6bdb05ee1b9f5e5.jpeg~tplv-tiktokx-origin.image?dr=14566&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=9b759fb9&idc=my3",
                        "unknown_fields": [
                          "platform_specific.tiktok.trend"
                        ],
                        "url": "https://www.tiktok.com/tag/cooking"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 741,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "hashtag",
                          "id": "18973",
                          "url": "https://www.tiktok.com/tag/cooking"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokHashtagResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact post and view counts",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.hashtag",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "hashtag",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/hashtag_posts": {
      "get": {
        "description": "Returns the top public videos and photo posts under a TikTok hashtag, in TikTok's own order, from the hashtag's link, its name or its share link. Each post comes with its caption, hashtags, author username, play count, cover and a video link that plays without TikTok's cookies. A hashtag TikTok doesn't have returns not_found.\n\nReturns `{data, page, meta}`: `data` holds up to 10 `Post` items (the shared schema, the same on every platform), TikTok's ranking of the hashtag's top posts (the order its embed shows). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/hashtag_posts/ (Markdown: https://socialtap.dev/docs/reference/tiktok/hashtag_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/hashtag_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/hashtag_posts/"
        },
        "operationId": "tiktok.hashtag_posts.list",
        "parameters": [
          {
            "description": "A TikTok hashtag page link (tiktok.com/tag/cooking), the hashtag itself with or without the # (cooking, #cooking), or the app's share link of a hashtag by its ID (m.tiktok.com/h5/share/tag/18973.html). Hashtags are case-insensitive and may be in any script (#料理); an all-digit hashtag (#2024) is read as a name, not an ID. A short link (vm.tiktok.com/…, tiktok.com/t/…) is not read: open it and send the link it lands on.",
            "example": "https://www.tiktok.com/tag/cooking",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "A TikTok hashtag page link (tiktok.com/tag/cooking), the hashtag itself with or without the # (cooking, #cooking), or the app's share link of a hashtag by its ID (m.tiktok.com/h5/share/tag/18973.html). Hashtags are case-insensitive and may be in any script (#料理); an all-digit hashtag (#2024) is read as a name, not an ID. A short link (vm.tiktok.com/…, tiktok.com/t/…) is not read: open it and send the link it lands on.",
              "examples": [
                "https://www.tiktok.com/tag/cooking"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 10,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 10,
              "maximum": 10,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "published_at",
                            "metrics.view_count"
                          ],
                          "author": {
                            "avatar_url": null,
                            "display_name": null,
                            "id": null,
                            "is_verified": null,
                            "url": "https://www.tiktok.com/@simplefood4you",
                            "username": "simplefood4you"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [
                            "garlic",
                            "recipe",
                            "cooking"
                          ],
                          "id": "7125823187908070661",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1024,
                              "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-maliva-p-0068/d6b067679b524a399bb8e68f345882b6_1659110004~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": "https://v16m.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast2a/tos-useast2a-pve-0068/ec65ddeb249343cfbb019992bd843314/?a=1233&bti=ODszNWYuMDE6&&bt=1538&ft=aEKfuqT0mIoPD12P~aII3wUDaFAbMeF~O5&mime_type=video_mp4&rc=NmRlZmg2OWk2NGg4PDc1ZkBpM3A5OzY6ZngzZTMzNzczM0BeYV9jXjEwNjExNDF…",
                              "width": 576
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 23500000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": null,
                              "board": null,
                              "country_code": null,
                              "is_ad": null,
                              "is_ai_generated": null,
                              "location": null,
                              "music": null
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2022-07-29T15:53:19Z",
                          "text": "I LOVE GARLIC 🙊🧄 #garlic #recipe #cooking #foodie #foodtiktok #food #foryou #fyp",
                          "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-maliva-p-0068/d6b067679b524a399bb8e68f345882b6_1659110004~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "mentions"
                          ],
                          "url": "https://www.tiktok.com/@simplefood4you/video/7125823187908070661"
                        },
                        {
                          "approximate_fields": [
                            "published_at",
                            "metrics.view_count"
                          ],
                          "author": {
                            "avatar_url": null,
                            "display_name": null,
                            "id": null,
                            "is_verified": null,
                            "url": "https://www.tiktok.com/@simplefood4you",
                            "username": "simplefood4you"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [
                            "eggsalad",
                            "recipe",
                            "cooking"
                          ],
                          "id": "7138098745467587846",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1024,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-p-0068/926e8b4cd33449ef9e9307fb540dc5ca_1661968133~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": "https://v16m.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast2a/tos-useast2a-ve-0068c001/236f04a83f694401b7ac0a6efb5eb85e/?a=1233&bti=ODszNWYuMDE6&&bt=1571&ft=aEKfuqT0mIoPD12P~aII3wUDaFAbMeF~O5&mime_type=video_mp4&rc=PDhnZWk1NDs2PDc6PGk8N0BpM2RlOzQ6ZndzZjMzNzczM0AzMGBiXzY0NS0x…",
                              "width": 576
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 12700000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": null,
                              "board": null,
                              "country_code": null,
                              "is_ad": null,
                              "is_ai_generated": null,
                              "location": null,
                              "music": null
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2022-08-31T17:48:45Z",
                          "text": "MY NEW OBSESSION 😋 #eggsalad #recipe #cooking #foodie #foodtiktok #food #foryou #fyp",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-p-0068/926e8b4cd33449ef9e9307fb540dc5ca_1661968133~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "mentions"
                          ],
                          "url": "https://www.tiktok.com/@simplefood4you/video/7138098745467587846"
                        },
                        {
                          "approximate_fields": [
                            "published_at",
                            "metrics.view_count"
                          ],
                          "author": {
                            "avatar_url": null,
                            "display_name": null,
                            "id": null,
                            "is_verified": null,
                            "url": "https://www.tiktok.com/@simplefood4you",
                            "username": "simplefood4you"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [
                            "recipe",
                            "cooking",
                            "foodie"
                          ],
                          "id": "7140666669512297733",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 1024,
                              "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-maliva-p-0068/e27fd71359da4b5c8141a0b5b35e2c9b_1662566028~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": "https://v16m.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast2a/tos-useast2a-ve-0068c001/23eb70e48c2d4ecbb93c4400f231aa78/?a=1233&bti=ODszNWYuMDE6&&bt=1358&ft=aEKfuqT0mIoPD12P~aII3wUDaFAbMeF~O5&mime_type=video_mp4&rc=NDVnPDc7NjkzZGg5N2Q4NUBpanU2djQ6ZnhlZjMzNzczM0AuX2AuYWNgNS0x…",
                              "width": 576
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 47900000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": null,
                              "board": null,
                              "country_code": null,
                              "is_ad": null,
                              "is_ai_generated": null,
                              "location": null,
                              "music": null
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2022-09-07T15:53:36Z",
                          "text": "World famous tortilla wrap @SmakapåTrollhättan this Friday 💥 @citytrollhattan #recipe #cooking #foodie #foodtiktok #food #foryou #fyp",
                          "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-maliva-p-0068/e27fd71359da4b5c8141a0b5b35e2c9b_1662566028~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "mentions"
                          ],
                          "url": "https://www.tiktok.com/@simplefood4you/video/7140666669512297733"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "hashtag",
                          "id": "18973",
                          "url": "https://www.tiktok.com/tag/cooking"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokHashtag_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Top videos and photo posts under a hashtag",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.hashtag_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "TikTok's ranking of the hashtag's top posts (the order its embed shows)",
          "page_max": 10,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/liked_posts": {
      "get": {
        "description": "Returns the videos and photo posts a TikTok account has liked, most recent like first, for accounts that show their likes publicly. Each post has its author, caption, hashtags, publish time, duration, cover, sound and view, like, comment and share counts. Send a username, profile link or user ID.\n\nReturns `{data, page, meta}`: `data` holds up to 30 `Post` items (the shared schema, the same on every platform), most recent like first (when the account liked each post). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/liked_posts/ (Markdown: https://socialtap.dev/docs/reference/tiktok/liked_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/liked_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/liked_posts/"
        },
        "operationId": "tiktok.liked_posts.list",
        "parameters": [
          {
            "description": "TikTok username with or without the @, a profile URL (tiktok.com/@sia) or a numeric user ID.",
            "example": "sia",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "TikTok username with or without the @, a profile URL (tiktok.com/@sia) or a numeric user ID.",
              "examples": [
                "sia"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 30,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 30,
              "maximum": 30,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count"
                          ],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/19ab9e75d2cb7105bcdb7364d595547b~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=0e5e0a55&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Shivaeya",
                            "id": "7289621882989610027",
                            "is_verified": true,
                            "url": "https://www.tiktok.com/@diljitdosanjh",
                            "username": "diljitdosanjh"
                          },
                          "coauthors": [],
                          "duration_ms": 30000,
                          "hashtags": [],
                          "id": "7617097437886369037",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": true,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 30000,
                              "expires_at": null,
                              "height": 1024,
                              "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/o4DEAEsA3Qut3FtEuScfFnmfBnAACRg4qpIVAD~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 576
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 374,
                            "like_count": 39600,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 1556,
                            "share_count": 1507,
                            "view_count": 1400000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAKj-dBnpJzzG7lV1VPVSCv9ehd7kGs_zkXsc8j2CA_s1PJaPNaYgjR_XBbvGmZ6fI",
                              "board": null,
                              "country_code": null,
                              "is_ad": true,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "Meditação Sonora",
                                "cover_url": "https://p16-common.tiktokcdn-us.com/tos-alisg-v-2774/oAeQk8AaIEqNBDABJMptBDiBgI1wQQAfgCEFEZ~tplv-tiktokx-cropcenter:720:720.jpeg?dr=9584&t=4d5b0474&ps=933b5bde&shp=08d74b56&shcp=81f88b70&idc=useast5",
                                "duration_ms": 56000,
                                "id": "7602243273784690705",
                                "is_original": false,
                                "play_url": "https://sf19.tiktokcdn-us.com/obj/tos-alisg-ve-2774/osve3ey2GDoTLbsahCIZTegFACgwQEcATIziIF",
                                "title": "Prosperidade Gravada no Éter"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-03-14T13:09:13Z",
                          "text": "BRAND NEW BANGER RANJHA 😍 🇮🇳 X 🇦🇺 X 🇫🇷 X 🇺🇸",
                          "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/o4DEAEsA3Qut3FtEuScfFnmfBnAACRg4qpIVAD~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@diljitdosanjh/video/7617097437886369037"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count"
                          ],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/19ab9e75d2cb7105bcdb7364d595547b~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=0e5e0a55&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Shivaeya",
                            "id": "7289621882989610027",
                            "is_verified": true,
                            "url": "https://www.tiktok.com/@diljitdosanjh",
                            "username": "diljitdosanjh"
                          },
                          "coauthors": [],
                          "duration_ms": 44000,
                          "hashtags": [],
                          "id": "7617009024755715341",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": true,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 44000,
                              "expires_at": null,
                              "height": 1026,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/oofp2pRqEDDtj1mEmDF0BIRbDV1nIgBfQJAS0A~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 576
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 1024,
                            "like_count": 160800,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 13294,
                            "share_count": 9044,
                            "view_count": 2100000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAKj-dBnpJzzG7lV1VPVSCv9ehd7kGs_zkXsc8j2CA_s1PJaPNaYgjR_XBbvGmZ6fI",
                              "board": null,
                              "country_code": null,
                              "is_ad": true,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "Shivaeya",
                                "cover_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/19ab9e75d2cb7105bcdb7364d595547b~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=0e5e0a55&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 44000,
                                "id": "7617009426167925517",
                                "is_original": true,
                                "play_url": "https://v16m.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast5/tos-useast5-v-27dcd7-tx/oMIHtDGYL2v1aYgfdT3uECQoOlgQYkVeAThfmI/?a=1233&bti=ODszNWYuMDE6&&bt=125&ft=GSDrKInz7Tht7gyGXq8Zmo&mime_type=audio_mpeg&rc=PDg4ZGc4ZzpnPDxoMzs8M0BpanEzdXM5cmhqOTMzZzU8NEA1MTUuYF8yXzYxYF8xLi40…",
                                "title": "original sound"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-03-14T07:26:48Z",
                          "text": "ਰਾਂਝਾ Brand New Banger OUT NOW 🎧",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/oofp2pRqEDDtj1mEmDF0BIRbDV1nIgBfQJAS0A~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@diljitdosanjh/video/7617009024755715341"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count"
                          ],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/60583b1e7d53d4fc0ee14d9d3b74c895~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=b5510f52&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Showakademiet AS",
                            "id": "6952242654495294470",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@showakademiet",
                            "username": "showakademiet"
                          },
                          "coauthors": [],
                          "duration_ms": 47000,
                          "hashtags": [
                            "teacher",
                            "student",
                            "music"
                          ],
                          "id": "7594538655952178454",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 47000,
                              "expires_at": null,
                              "height": 1024,
                              "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-no1a-p-0037-no/ogSAZYNBIOWi4FIBc41iEjJPIBhGJoUxLalRu~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 576
                            }
                          ],
                          "mentions": [
                            "siaarchive",
                            "noahwoster",
                            "leandamusic"
                          ],
                          "metrics": {
                            "comment_count": 206,
                            "like_count": 41400,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 2497,
                            "share_count": 1260,
                            "view_count": 365700
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAA21zolPrYybEqz4V3ClyaPYLQ-6obQXKpXKAs74TmDU0VTXf1F5Tfi-cHD3KsI9uy",
                              "board": null,
                              "country_code": null,
                              "is_ad": false,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "Showakademiet AS",
                                "cover_url": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/60583b1e7d53d4fc0ee14d9d3b74c895~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=b5510f52&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 47000,
                                "id": "7594538666412755734",
                                "is_original": true,
                                "play_url": "https://v16m.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/no1a/tos-no1a-v-2370-no/oEJCAx0EldrBlAqOwZyLpfiqiKBEBAs2OOMAAE/?a=1233&bti=ODszNWYuMDE6&&bt=125&ft=GSDrKInz7Tht7gyGXq8Zmo&mime_type=audio_mpeg&rc=M2U7OnA5cmZtODMzbzU8NUBpM2U7OnA5cmZtODMzbzU8NUA0bWEtMmRzZWZhLS1kMTFzYSM0bWEt…",
                                "title": "original sound"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-01-12T18:08:48Z",
                          "text": "student and teacher in perfect harmo🥰#teacher #student #music #chandelier @SiaArchive @noahwoster @Leanda Klingsheim",
                          "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-no1a-p-0037-no/ogSAZYNBIOWi4FIBc41iEjJPIBhGJoUxLalRu~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@showakademiet/video/7594538655952178454"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1330,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "6811538513018012677",
                          "url": "https://www.tiktok.com/@sia"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokLiked_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "What an account liked, most recent like first",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.liked_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "most recent like first (when the account liked each post)",
          "page_max": 30,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/live": {
      "get": {
        "description": "Returns whether a TikTok account is LIVE now, with its viewer count, title and stream links, from a username, profile or LIVE link, or user ID. A room on air has its current viewers, total entries, title, cover and start time, and HLS, DASH and HTTP-FLV links for every quality TikTok serves, with when each expires. Otherwise you get the latest room, ended. The host comes with its ID, secUid, display name, verified badge and follower count.\n\nReturns `{data, meta}`: `data` is a `Live` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/live/ (Markdown: https://socialtap.dev/docs/reference/tiktok/live/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/live/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/live/"
        },
        "operationId": "tiktok.live.get",
        "parameters": [
          {
            "description": "TikTok username with or without the @ (aljazeeraenglish, @aljazeeraenglish), a profile or LIVE page URL (tiktok.com/@aljazeeraenglish, tiktok.com/@aljazeeraenglish/live), or a numeric user ID (tiktok.com/share/user/<id> or the bare ID). Usernames are case-insensitive.",
            "example": "aljazeeraenglish",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "TikTok username with or without the @ (aljazeeraenglish, @aljazeeraenglish), a profile or LIVE page URL (tiktok.com/@aljazeeraenglish, tiktok.com/@aljazeeraenglish/live), or a numeric user ID (tiktok.com/share/user/<id> or the bare ID). Usernames are case-insensitive.",
              "examples": [
                "aljazeeraenglish"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "category": null,
                        "ended_at": null,
                        "host": {
                          "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/f569c9cd13cf1ccee624a4ae1b0b4c4e~tplv-tiktokx-cropcenter:1080:1080.webp?dr=9640&refresh_token=b70569e5&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=fdd36af4&idc=useast5",
                          "display_name": "Al Jazeera English",
                          "id": "7074562477175424046",
                          "is_verified": true,
                          "url": "https://www.tiktok.com/@aljazeeraenglish",
                          "username": "aljazeeraenglish"
                        },
                        "id": "7703236637299444493",
                        "metrics": {
                          "concurrent_viewer_count": 4935,
                          "like_count": null,
                          "view_count": 926646
                        },
                        "platform": "tiktok",
                        "platform_specific": {
                          "tiktok": {
                            "host_follower_count": 16752217,
                            "host_sec_uid": "MS4wLjABAAAAtS2tPZtfESngqzjzrwwUu0M1LUlx1MjODxCDecgBvwBcyquIg56vBb_2I0BaW574",
                            "is_age_restricted": null,
                            "is_subscriber_only": false,
                            "stream_id": "3579127593564111804"
                          }
                        },
                        "post_id": null,
                        "scheduled_start_at": null,
                        "started_at": "2026-11-01T16:14:18Z",
                        "status": "live",
                        "streams": [
                          {
                            "bitrate_kbps": 10671,
                            "expires_at": "2026-10-25T18:00:00Z",
                            "format": "hls",
                            "height": 1080,
                            "is_audio_only": false,
                            "quality": "Original",
                            "url": "https://pull-hls-f16-tt01.tiktokcdn-us.com/game/stream-3579127593564111804/index.m3u8?expire=4070908800&sign=SCRUBBED",
                            "video_codec": "h264",
                            "width": 1920
                          },
                          {
                            "bitrate_kbps": 10671,
                            "expires_at": "2026-10-25T18:00:00Z",
                            "format": "dash",
                            "height": 1080,
                            "is_audio_only": false,
                            "quality": "Original",
                            "url": "https://pull-f5-tt01.tiktokcdn-us.com/game/stream-3579127593564111804/index.mpd?auth_mode=2&expire=4070908800&sign=SCRUBBED",
                            "video_codec": "h264",
                            "width": 1920
                          },
                          {
                            "bitrate_kbps": 10671,
                            "expires_at": "2026-10-25T18:00:00Z",
                            "format": "flv",
                            "height": 1080,
                            "is_audio_only": false,
                            "quality": "Original",
                            "url": "https://pull-f5-tt01.tiktokcdn-us.com/game/stream-3579127593564111804.flv?expire=4070908800&sign=SCRUBBED",
                            "video_codec": "h264",
                            "width": 1920
                          }
                        ],
                        "text": null,
                        "thumbnail_url": "https://p16-webcast.tiktokcdn-us.com/webcast-oci-tx/7628418490097126158~tplv-obj.image",
                        "title": "Al Jazeera English TikTok LIVE",
                        "unknown_fields": [],
                        "url": "https://www.tiktok.com/@aljazeeraenglish/live"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 476,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "7703236637299444493",
                          "url": "https://www.tiktok.com/@aljazeeraenglish/live"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokLiveResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "no_live": {
                    "$ref": "#/components/examples/no_live"
                  },
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.\n\n`no_live`: The account exists but has no live broadcast to show: nothing on air or scheduled, and no past broadcast the platform still shows. Do not retry now. Ask again later, when the account may be live.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "On-air status, viewer count and stream links",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.live",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "live",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/place_posts": {
      "get": {
        "description": "Returns the public TikTok videos and photo posts tagged at a place, such as a city, venue or business, from the place's link or ID. Each has its caption, hashtags, mentions, publish time, duration, cover, photos, author, sound, the tagged place and engagement counts, a page at a time in TikTok's own order.\n\nReturns `{data, page, meta}`: `data` holds up to 30 `Post` items (the shared schema, the same on every platform), TikTok's ranking of the place's posts (the order its place page shows). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/place_posts/ (Markdown: https://socialtap.dev/docs/reference/tiktok/place_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/place_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/place_posts/"
        },
        "operationId": "tiktok.place_posts.list",
        "parameters": [
          {
            "description": "A TikTok place link (the place page's tiktok.com/place/Orlando-22535796481476942, as a post's location tag opens it) or the place's numeric ID (the number at the end of that link).",
            "example": "https://www.tiktok.com/place/Orlando-22535796481476942",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "A TikTok place link (the place page's tiktok.com/place/Orlando-22535796481476942, as a post's location tag opens it) or the place's numeric ID (the number at the end of that link).",
              "examples": [
                "https://www.tiktok.com/place/Orlando-22535796481476942"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 30,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 30,
              "maximum": 30,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count",
                            "metrics.comment_count"
                          ],
                          "author": {
                            "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/fe5cad2262d05c7f0bbd85761a6796ca~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=f43af3c9&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Amanda Ochoa",
                            "id": "6851399188057293830",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@seckcmofo",
                            "username": "seckcmofo"
                          },
                          "coauthors": [],
                          "duration_ms": 23000,
                          "hashtags": [],
                          "id": "7206830958417399082",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 23000,
                              "expires_at": null,
                              "height": 1280,
                              "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/a7e6db6f6cfa4081a46253de5c9f9566~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 78600,
                            "like_count": 18600000,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 3125831,
                            "share_count": 2200000,
                            "view_count": 108900000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAShmDbhbRbSchO-URvkORjrZYa8FKPUGIZJL87oshYwTqr-PEPLeDLv8eCf-FcIpk",
                              "board": null,
                              "country_code": null,
                              "is_ad": false,
                              "is_ai_generated": false,
                              "location": {
                                "address": "Florida, United States",
                                "category": "Place and Address",
                                "city": null,
                                "id": "22535796481476942",
                                "name": "Orlando"
                              },
                              "music": {
                                "author_name": "Amanda Ochoa",
                                "cover_url": "https://p19-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/fe5cad2262d05c7f0bbd85761a6796ca~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=f43af3c9&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 23000,
                                "id": "7206830978080394030",
                                "is_original": true,
                                "play_url": "https://v19.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast5/tos-useast5-v-27dcd7-tx/afb15e505acb43489f7d906b1ea0f0ae/?a=1233&bti=ODszNWYuMDE6&&bt=125&ft=GSDrKInz7Th6OgyGXq8Zmo&mime_type=audio_mpeg&rc=MzxrOTM6Zjt2ajMzZzU8NEBpMzxrOTM6Zjt2ajMzZzU8NEBgMGhmcjRncS5gLS1kMS9zYSNgMGh…",
                                "title": "original sound"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2023-03-04T23:05:04Z",
                          "text": null,
                          "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/a7e6db6f6cfa4081a46253de5c9f9566~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@seckcmofo/video/7206830958417399082"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count",
                            "metrics.comment_count"
                          ],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/2d8fcfd40038a0e394c30c3a3f7903ad~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=9f48434d&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Luz Yarielis🦋",
                            "id": "3809075",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@yrl.x",
                            "username": "yrl.x"
                          },
                          "coauthors": [],
                          "duration_ms": 31000,
                          "hashtags": [
                            "genderreveal",
                            "cakereveal"
                          ],
                          "id": "7318522822152686890",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 31000,
                              "expires_at": null,
                              "height": 1024,
                              "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/989ab6d736f749f9bd7c0220e0972a9a_1703976399~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 576
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 33100,
                            "like_count": 10100000,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 497357,
                            "share_count": 109300,
                            "view_count": 59200000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAzoRsrltK3Sy7mWcHu76fK6N2WLJ0_fuewD0S1_gAHaU",
                              "board": null,
                              "country_code": null,
                              "is_ad": false,
                              "is_ai_generated": false,
                              "location": {
                                "address": "Florida, United States",
                                "category": "Place and Address",
                                "city": null,
                                "id": "22535796481476942",
                                "name": "Orlando"
                              },
                              "music": {
                                "author_name": "Sydney Rose",
                                "cover_url": "https://p16-common.tiktokcdn-us.com/tos-alisg-v-2774/ooXz7fAPerUeA3GtW9fjfIQARLZlexhADAIQYY~tplv-tiktokx-cropcenter:720:720.jpeg?dr=9584&t=4d5b0474&ps=933b5bde&shp=08d74b56&shcp=81f88b70&idc=useast5",
                                "duration_ms": 60000,
                                "id": "6878996984686970882",
                                "is_original": false,
                                "play_url": "https://sf16.tiktokcdn-us.com/obj/tos-alisg-ve-2774/oYBexf0r3KfrMAMix2hVfXQMgfM5G42UC8hFAA",
                                "title": "Turning Page"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2023-12-30T22:46:37Z",
                          "text": "July 2024🤍 #genderreveal #cakereveal",
                          "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/989ab6d736f749f9bd7c0220e0972a9a_1703976399~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@yrl.x/video/7318522822152686890"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count",
                            "metrics.comment_count"
                          ],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/7311432654476935211~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=ea4a2a64&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Los_chicaneros",
                            "id": "6994035027688817669",
                            "is_verified": true,
                            "url": "https://www.tiktok.com/@los_chicaneros",
                            "username": "los_chicaneros"
                          },
                          "coauthors": [],
                          "duration_ms": 79000,
                          "hashtags": [],
                          "id": "7274680359336365355",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "es",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 79000,
                              "expires_at": null,
                              "height": 1024,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/0d0dd378d44f49ae93ea1a3ba876a459_1693768524~tplv-tiktokx-dmt-logom:tos-useast5-i-0068-tx/ocD9SEBInJ0tNC2egDb0AFAAgeHAAkDEMAXR10.image?dr=9634&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b…",
                              "type": "video",
                              "url": null,
                              "width": 576
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 71900,
                            "like_count": 8100000,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 554390,
                            "share_count": 837600,
                            "view_count": 92700000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAA8W4dpejhnqJSEbWYZWWuSkWK1-AehqI5plRzUD8EgrPWZCEfKLzDiZIjbA_VdJ0l",
                              "board": null,
                              "country_code": null,
                              "is_ad": false,
                              "is_ai_generated": false,
                              "location": {
                                "address": "Florida, United States",
                                "category": "Place and Address",
                                "city": null,
                                "id": "22535796481476942",
                                "name": "Orlando"
                              },
                              "music": {
                                "author_name": "Los_chicaneros",
                                "cover_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/7311432654476935211~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=ea4a2a64&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 79000,
                                "id": "7274680398527892270",
                                "is_original": true,
                                "play_url": "https://v19.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast5/tos-useast5-v-27dcd7-tx/oQmEh90eg2GJCET0kAEDH1fUUCD0Smt2BPAozA/?a=1233&bti=ODszNWYuMDE6&&bt=125&ft=GSDrKInz7Th6OgyGXq8Zmo&mime_type=audio_mpeg&rc=M2lmazk6Zm1nbTMzZzU8NEBpM2lmazk6Zm1nbTMzZzU8NEBoMW5ycjRfam5gLS1kMS9zY…",
                                "title": "original sound"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2023-09-03T19:15:23Z",
                          "text": "Como cree mi familia que vivimos en Estados Unidos",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/0d0dd378d44f49ae93ea1a3ba876a459_1693768524~tplv-tiktokx-dmt-logom:tos-useast5-i-0068-tx/ocD9SEBInJ0tNC2egDb0AFAAgeHAAkDEMAXR10.image?dr=9634&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@los_chicaneros/video/7274680359336365355"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 751,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "place",
                          "id": "22535796481476942",
                          "url": "https://www.tiktok.com/place/Orlando-22535796481476942"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokPlace_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Videos and photo posts tagged at a place",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.place_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "TikTok's ranking of the place's posts (the order its place page shows)",
          "page_max": 30,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/playlist_posts": {
      "get": {
        "description": "Returns the public videos and photo posts of a TikTok playlist or collection, in its own order, from its link or numeric ID. Each post has its caption, hashtags, mentions, publish time, duration, cover, photos, sound, author and view, like, comment and share counts.\n\nReturns `{data, page, meta}`: `data` holds up to 30 `Post` items (the shared schema, the same on every platform), the playlist's own order (its owner's for a playlist, the order TikTok shows a collection's posts in). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/playlist_posts/ (Markdown: https://socialtap.dev/docs/reference/tiktok/playlist_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/playlist_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/playlist_posts/"
        },
        "operationId": "tiktok.playlist_posts.list",
        "parameters": [
          {
            "description": "A TikTok playlist or collection link (tiktok.com/@tiktok/playlist/In-The-Mix-7516638364301265695, tiktok.com/@tiktok/collection/Summer-of-Sports-7394627756635573022) or its numeric ID (the number at the end of that link).",
            "example": "https://www.tiktok.com/@tiktok/playlist/In-The-Mix-7516638364301265695",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "A TikTok playlist or collection link (tiktok.com/@tiktok/playlist/In-The-Mix-7516638364301265695, tiktok.com/@tiktok/collection/Summer-of-Sports-7394627756635573022) or its numeric ID (the number at the end of that link).",
              "examples": [
                "https://www.tiktok.com/@tiktok/playlist/In-The-Mix-7516638364301265695"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 30,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 30,
              "maximum": 30,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count"
                          ],
                          "author": {
                            "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/ba67b11de451691939223e9d978e613a~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=2542d347&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "TikTok",
                            "id": "107955",
                            "is_verified": true,
                            "url": "https://www.tiktok.com/@tiktok",
                            "username": "tiktok"
                          },
                          "coauthors": [],
                          "duration_ms": 1560000,
                          "hashtags": [],
                          "id": "7516636731223837983",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 1560000,
                              "expires_at": null,
                              "height": 1024,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/oMr6rAA6QCIh5zBgE2FEAqDfIoAjTeAQIifXqO~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 576
                            }
                          ],
                          "mentions": [
                            "zaralarsson"
                          ],
                          "metrics": {
                            "comment_count": 4942,
                            "like_count": 15800,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 1439,
                            "share_count": 993,
                            "view_count": 872100
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAv7iSuuXDJGDvJkmH_vz1qkDZYo1apxgzaxdBSeIuPiM",
                              "board": null,
                              "country_code": null,
                              "is_ad": false,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "TikTok",
                                "cover_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/ba67b11de451691939223e9d978e613a~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=2542d347&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 1560000,
                                "id": "7516636859129137951",
                                "is_original": true,
                                "play_url": "https://v16m.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast8/tos-useast8-v-27dcd7-tx2/osuoeeOg5AeTGXAIACRIEvCq6IoLINYyQirUAC/?a=1233&bti=ODszNWYuMDE6&&bt=125&ft=GSDrKInz7ThGmgyGXq8Zmo&mime_type=audio_mpeg&rc=anI1bW45cnc6NDMzaTU8NEBpanI1bW45cnc6NDMzaTU8NEBrcDFeMmRzXjVhLS1kMTJ…",
                                "title": "original sound"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2025-06-16T19:49:53Z",
                          "text": "ty @Zara Larsson for yapping about TikTok and music with us and Jack Coyne for In The Mix! 💖🌈",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/oMr6rAA6QCIh5zBgE2FEAqDfIoAjTeAQIifXqO~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@tiktok/video/7516636731223837983"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count"
                          ],
                          "author": {
                            "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/ba67b11de451691939223e9d978e613a~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=2542d347&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "TikTok",
                            "id": "107955",
                            "is_verified": true,
                            "url": "https://www.tiktok.com/@tiktok",
                            "username": "tiktok"
                          },
                          "coauthors": [],
                          "duration_ms": 64000,
                          "hashtags": [],
                          "id": "7516614421221821727",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": true,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 64000,
                              "expires_at": null,
                              "height": 1024,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/oklCIV7hODARYldRDGFfERoDNEcARB4UIIf8QE~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 576
                            }
                          ],
                          "mentions": [
                            "zaralarsson",
                            "iamdoechii_"
                          ],
                          "metrics": {
                            "comment_count": 2625,
                            "like_count": 195100,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 6200,
                            "share_count": 1329,
                            "view_count": 6100000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAv7iSuuXDJGDvJkmH_vz1qkDZYo1apxgzaxdBSeIuPiM",
                              "board": null,
                              "country_code": null,
                              "is_ad": true,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "TikTok",
                                "cover_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/ba67b11de451691939223e9d978e613a~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=2542d347&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 64000,
                                "id": "7516614380553833247",
                                "is_original": true,
                                "play_url": "https://v16m.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast8/tos-useast8-v-27dcd7-tx2/ow7ncoDTIFCEIxBUOAEVAwUAEyGefJEgooiCAz/?a=1233&bti=ODszNWYuMDE6&&bt=125&ft=GSDrKInz7ThGmgyGXq8Zmo&mime_type=audio_mpeg&rc=anM8d3M5cjc5NDMzaTU8NEBpanM8d3M5cjc5NDMzaTU8NEBnNC1iMmRzLzVhLS1kMTJ…",
                                "title": "original sound"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2025-06-16T18:23:13Z",
                          "text": "we'd like to see a collab 👀 @Zara Larsson @Doechii",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/oklCIV7hODARYldRDGFfERoDNEcARB4UIIf8QE~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@tiktok/video/7516614421221821727"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count"
                          ],
                          "author": {
                            "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/ba67b11de451691939223e9d978e613a~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=2542d347&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "TikTok",
                            "id": "107955",
                            "is_verified": true,
                            "url": "https://www.tiktok.com/@tiktok",
                            "username": "tiktok"
                          },
                          "coauthors": [],
                          "duration_ms": 12000,
                          "hashtags": [],
                          "id": "7515146520912530718",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": true,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 12000,
                              "expires_at": null,
                              "height": 1024,
                              "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/owEIPfMYWAy3lps2AjeIAErIf93QgqA8AQl2FQ~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 576
                            }
                          ],
                          "mentions": [
                            "zaralarsson",
                            "trackstarshow"
                          ],
                          "metrics": {
                            "comment_count": 1848,
                            "like_count": 35200,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 1900,
                            "share_count": 647,
                            "view_count": 6300000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAv7iSuuXDJGDvJkmH_vz1qkDZYo1apxgzaxdBSeIuPiM",
                              "board": null,
                              "country_code": null,
                              "is_ad": true,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "TikTok",
                                "cover_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/ba67b11de451691939223e9d978e613a~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=2542d347&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 12000,
                                "id": "7515151632871590687",
                                "is_original": true,
                                "play_url": "https://v16m.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast8/tos-useast8-v-27dcd7-tx2/oAA8BLhJMiBATKZAE0iB4qfIEA6lAd24iqLW5E/?a=1233&bti=ODszNWYuMDE6&&bt=125&ft=GSDrKInz7ThGmgyGXq8Zmo&mime_type=audio_mpeg&rc=MzR1eHI5cmVsNDMzaTU8NEBpMzR1eHI5cmVsNDMzaTU8NEAxZzM2MmRjcTJhLS1kMTJ…",
                                "title": "original sound"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2025-06-12T19:26:53Z",
                          "text": "@Zara Larsson’s In The Mix episode with Jack Coyne from @Track Star will be LIVE on @TikTok. Tune in June 13th, 8pm EST!",
                          "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/owEIPfMYWAy3lps2AjeIAErIf93QgqA8AQl2FQ~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@tiktok/video/7515146520912530718"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 625,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "playlist",
                          "id": "7516638364301265695",
                          "url": "https://www.tiktok.com/@tiktok/playlist/In-The-Mix-7516638364301265695"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokPlaylist_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Videos in a playlist or collection, in its order",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.playlist_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the playlist's own order (its owner's for a playlist, the order TikTok shows a collection's posts in)",
          "page_max": 30,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/playlists": {
      "get": {
        "description": "Returns a TikTok account's playlists and public collections, from a username, profile link, user ID or secUid. Each has its title, link, cover, owner and exact post count. Playlists come first, in the order the account set.\n\nReturns `{data, page, meta}`: `data` holds up to 30 `Playlist` items (the shared schema, the same on every platform), the account's playlists in the order it set, then its public collections. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/playlists/ (Markdown: https://socialtap.dev/docs/reference/tiktok/playlists/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/playlists/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/playlists/"
        },
        "operationId": "tiktok.playlists.list",
        "parameters": [
          {
            "description": "TikTok username with or without the @, a profile URL (tiktok.com/@tiktok), a numeric user ID or a secUid (MS4wLjABAAAA…).",
            "example": "tiktok",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "TikTok username with or without the @, a profile URL (tiktok.com/@tiktok), a numeric user ID or a secUid (MS4wLjABAAAA…).",
              "examples": [
                "tiktok"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 30,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 30,
              "maximum": 30,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "description": null,
                          "id": "7681171537575824159",
                          "is_collaborative": null,
                          "metrics": {
                            "post_count": 3
                          },
                          "owner": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/ba67b11de451691939223e9d978e613a~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=059fedb3&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "TikTok",
                            "id": "107955",
                            "is_verified": true,
                            "url": "https://www.tiktok.com/@tiktok",
                            "username": "tiktok"
                          },
                          "platform": "tiktok",
                          "platform_specific": {},
                          "platform_type": "mix",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/o8UZ7AA11Ciogu5XByiiAPBcCSAIMnAIEBfaK7~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": "Songs Of The Summer 2026",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@tiktok/playlist/Songs%20Of%20The%20Summer%202026-7681171537575824159"
                        },
                        {
                          "approximate_fields": [],
                          "description": null,
                          "id": "7659874208872221471",
                          "is_collaborative": null,
                          "metrics": {
                            "post_count": 6
                          },
                          "owner": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/ba67b11de451691939223e9d978e613a~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=059fedb3&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "TikTok",
                            "id": "107955",
                            "is_verified": true,
                            "url": "https://www.tiktok.com/@tiktok",
                            "username": "tiktok"
                          },
                          "platform": "tiktok",
                          "platform_specific": {},
                          "platform_type": "mix",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/oM4EVAFCUEDiowAA0eAAfLEzqLIhR4OEVASzPC~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": "Behind The Breakthrough",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@tiktok/playlist/Behind%20The%20Breakthrough-7659874208872221471"
                        },
                        {
                          "approximate_fields": [],
                          "description": null,
                          "id": "7516638364301265695",
                          "is_collaborative": null,
                          "metrics": {
                            "post_count": 24
                          },
                          "owner": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/ba67b11de451691939223e9d978e613a~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=059fedb3&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "TikTok",
                            "id": "107955",
                            "is_verified": true,
                            "url": "https://www.tiktok.com/@tiktok",
                            "username": "tiktok"
                          },
                          "platform": "tiktok",
                          "platform_specific": {},
                          "platform_type": "mix",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/oMr6rAA6QCIh5zBgE2FEAqDfIoAjTeAQIifXqO~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": "In The Mix",
                          "type": "playlist",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@tiktok/playlist/In%20The%20Mix-7516638364301265695"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 826,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "107955",
                          "url": "https://www.tiktok.com/@tiktok"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "end"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokPlaylistsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Account playlists and public collections",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.playlists",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the account's playlists in the order it set, then its public collections",
          "page_max": 30,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "playlist",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/post": {
      "get": {
        "description": "Returns a public TikTok video or photo post from its link, share link or ID, with its view, like, comment, share and save counts. It also has the caption, author, publish time, hashtags, tagged accounts, a direct video file link or every slideshow photo, the cover, sound, tagged place, and ad and AI labels.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/post/ (Markdown: https://socialtap.dev/docs/reference/tiktok/post/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/post/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/post/"
        },
        "operationId": "tiktok.post.get",
        "parameters": [
          {
            "description": "TikTok video or photo post link (web, mobile, embed or share link) or a numeric post ID.",
            "example": "https://www.tiktok.com/@scout2015/video/6718335390845095173",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "TikTok video or photo post link (web, mobile, embed or share link) or a numeric post ID.",
              "examples": [
                "https://www.tiktok.com/@niinoclock/video/7673108027645414678"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "duration_ms",
                          "media[].duration_ms",
                          "metrics.view_count"
                        ],
                        "author": {
                          "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/4cbe05e194623e3f19aef975d9fdf26c~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=1a7ec680&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                          "display_name": "Scout, Suki & Stella",
                          "id": "53279706535428096",
                          "is_verified": true,
                          "url": "https://www.tiktok.com/@scout2015",
                          "username": "scout2015"
                        },
                        "coauthors": [],
                        "duration_ms": 10000,
                        "hashtags": [
                          "foryoupage",
                          "petsoftiktok",
                          "aesthetic"
                        ],
                        "id": "6718335390845095173",
                        "is_nsfw": false,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": "en",
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": 10000,
                            "expires_at": "2026-10-25T18:00:00Z",
                            "height": 1024,
                            "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-maliva-p-0068/2367c7d45cf54a1397abd0e72bf22eac~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                            "type": "video",
                            "url": "https://v19.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast5/tos-useast5-ve-0068c002-tx/15fbafb086324317bf77a649580b1f95/?a=1233&bti=ODszNWYuMDE6&&bt=2389&ft=aEKfuqT0mIoPD12Qd0iI3wUM0_AbMeF~O5&mime_type=video_mp4&rc=ODw1Z2gzZ2Q1ODo4aGdnZUBpM245aWhvZ3U4bjMzZzczM0AzNWA1MWJiNWEx…",
                            "width": 576
                          }
                        ],
                        "mentions": [],
                        "metrics": {
                          "comment_count": 5716,
                          "like_count": 35200,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": 649,
                          "share_count": 1518,
                          "view_count": 159700
                        },
                        "platform": "tiktok",
                        "platform_specific": {
                          "tiktok": {
                            "author_follower_count": null,
                            "author_sec_uid": "MS4wLjABAAAAPZWNdkF_cmVSPCvV0Y6MCsH29mlAOlMOX3ikzGvlfMm3K6OMZv-JrRImpEHxdIMI",
                            "board": null,
                            "country_code": "US",
                            "is_ad": false,
                            "is_ai_generated": false,
                            "location": null,
                            "music": {
                              "author_name": "tiff",
                              "cover_url": "https://p19-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/62c59c8c91226b51c36d2338519eb63e~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=ae9b518c&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                              "duration_ms": 10000,
                              "id": "6689804660171082501",
                              "is_original": true,
                              "play_url": "https://v19.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast5/tos-useast5-v-27dcd7-tx/fdec9588d6684e7d97da29739b9d0abf/?a=1233&bti=ODszNWYuMDE6&&bt=125&ft=GSDrKInz7ThMDnRGXq8Zmo&mime_type=audio_mpeg&rc=am48ZmQ6ZnFxNzMzNzU8M0Bpam48ZmQ6ZnFxNzMzNzU8M0BpNWRhcjRfaGBgLS1kMTZzYSNpNWR…",
                              "title": "original sound"
                            }
                          }
                        },
                        "platform_type": "video",
                        "published_at": "2019-07-27T13:32:38Z",
                        "text": "Scramble up ur name & I’ll try to guess it😍❤️ #foryoupage #petsoftiktok #aesthetic",
                        "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-maliva-p-0068/2367c7d45cf54a1397abd0e72bf22eac~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                        "title": null,
                        "type": "video",
                        "unknown_fields": [
                          "coauthors"
                        ],
                        "url": "https://www.tiktok.com/@scout2015/video/6718335390845095173"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1140,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "6718335390845095173",
                          "url": "https://www.tiktok.com/@scout2015/video/6718335390845095173"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokPostResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Video or photo post with views, likes and media",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.post",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/posts": {
      "get": {
        "description": "Returns a TikTok account's public videos and photo posts, newest first, a page at a time, from a username, profile link, user ID or secUid. Each post has its caption, hashtags, mentions, publish time, duration, cover, photos and view, like, comment and share counts. Send since and until to read a date range.\n\nReturns `{data, page, meta}`: `data` holds up to 15 `Post` items (the shared schema, the same on every platform), newest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/posts/ (Markdown: https://socialtap.dev/docs/reference/tiktok/posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/posts/"
        },
        "operationId": "tiktok.posts.list",
        "parameters": [
          {
            "description": "TikTok username with or without the @, a profile URL (tiktok.com/@nasa), a numeric user ID or a secUid (MS4wLjABAAAA…).",
            "example": "@khaby.lame",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "TikTok username with or without the @, a profile URL (tiktok.com/@nasa), a numeric user ID or a secUid (MS4wLjABAAAA…).",
              "examples": [
                "nasa"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 15,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 15,
              "maximum": 15,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count",
                            "metrics.share_count"
                          ],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/08987e23b94057953fd4f1738694bf5f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=07918010&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Khabane lame",
                            "id": "127905465618821121",
                            "is_verified": true,
                            "url": "https://www.tiktok.com/@khaby.lame",
                            "username": "khaby.lame"
                          },
                          "coauthors": [],
                          "duration_ms": 9000,
                          "hashtags": [
                            "learnfromkhaby",
                            "comedy"
                          ],
                          "id": "7697307919943060767",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 9000,
                              "expires_at": null,
                              "height": 1280,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/oQbHQmFfa5VY3NlkEGDAQT00RzqAqBOETlEafj~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 7503,
                            "like_count": 305900,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 16282,
                            "share_count": 32600,
                            "view_count": 4600000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAwAg0rSzO65WQfz4RzQgGv2Xdv108BgPXhRrrmNVIHQZ9PO8-flwwRtEppYTS0OjA",
                              "board": null,
                              "country_code": null,
                              "is_ad": false,
                              "is_ai_generated": true,
                              "location": null,
                              "music": {
                                "author_name": "Khabane lame",
                                "cover_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/08987e23b94057953fd4f1738694bf5f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=07918010&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 9000,
                                "id": "7697308007327730462",
                                "is_original": true,
                                "play_url": "https://v16-webapp-prime.us.tiktok.com/video/tos/useast8/tos-useast8-v-27dcd7-tx2/oEEIAbfkyMVIeCnAjGGKYI9gqpqTImLAAfYo09/?a=1988&bti=ODszNWYuMDE6&&bt=125&ft=GcAInInz7Th~v-RGXq8Zmo&mime_type=audio_mpeg&rc=M2lybXI5cnE4ZTMzaTU8NEBpM2lybXI5cnE4ZTMzaTU8NEBxYG5tMmRrNjZhLS1kMTJzYSNxYG5t…",
                                "title": "original sound"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-16T16:46:21Z",
                          "text": "I guess is time to retire #learnfromkhaby #comedy 🥊",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/oQbHQmFfa5VY3NlkEGDAQT00RzqAqBOETlEafj~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@khaby.lame/video/7697307919943060767"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count",
                            "metrics.comment_count"
                          ],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/08987e23b94057953fd4f1738694bf5f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=07918010&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Khabane lame",
                            "id": "127905465618821121",
                            "is_verified": true,
                            "url": "https://www.tiktok.com/@khaby.lame",
                            "username": "khaby.lame"
                          },
                          "coauthors": [],
                          "duration_ms": 30000,
                          "hashtags": [
                            "learnfromkhaby",
                            "comedy"
                          ],
                          "id": "7694335322922044703",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 30000,
                              "expires_at": null,
                              "height": 1280,
                              "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/osAHzWAIipBAxVMie5CIDqxK0ArEREAAEKVSfn~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 12600,
                            "like_count": 690100,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 40145,
                            "share_count": 20800,
                            "view_count": 6900000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAwAg0rSzO65WQfz4RzQgGv2Xdv108BgPXhRrrmNVIHQZ9PO8-flwwRtEppYTS0OjA",
                              "board": null,
                              "country_code": null,
                              "is_ad": false,
                              "is_ai_generated": true,
                              "location": null,
                              "music": {
                                "author_name": "Khabane lame",
                                "cover_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/08987e23b94057953fd4f1738694bf5f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=07918010&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 30000,
                                "id": "7694335437137087262",
                                "is_original": true,
                                "play_url": "https://v16-webapp-prime.us.tiktok.com/video/tos/useast8/tos-useast8-v-27dcd7-tx2/o4fHr3qIArT5AEXEiCLVExDGAeqCAIOVe4joPR/?a=1988&bti=ODszNWYuMDE6&&bt=125&ft=GcAInInz7Th~v-RGXq8Zmo&mime_type=audio_mpeg&rc=M3lzeG45cm92ZTMzaTU8NEBpM3lzeG45cm92ZTMzaTU8NEBzNGtiMmRjXjBhLS1kMTJzYSNzNGti…",
                                "title": "original sound"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-08T16:31:16Z",
                          "text": "Was the ball out, or was it just my imagination? 🤨#learnfromkhaby #comedy",
                          "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/osAHzWAIipBAxVMie5CIDqxK0ArEREAAEKVSfn~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@khaby.lame/video/7694335322922044703"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count",
                            "metrics.share_count"
                          ],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/08987e23b94057953fd4f1738694bf5f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=07918010&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Khabane lame",
                            "id": "127905465618821121",
                            "is_verified": true,
                            "url": "https://www.tiktok.com/@khaby.lame",
                            "username": "khaby.lame"
                          },
                          "coauthors": [],
                          "duration_ms": 34000,
                          "hashtags": [
                            "learnfromkhaby",
                            "comedy"
                          ],
                          "id": "7691740195418377502",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 34000,
                              "expires_at": null,
                              "height": 1280,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/o0jRDQRMAbfFAlZX8eqGQcARBqerRfAHR7gVSU~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 7325,
                            "like_count": 418500,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 20087,
                            "share_count": 23900,
                            "view_count": 5000000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAwAg0rSzO65WQfz4RzQgGv2Xdv108BgPXhRrrmNVIHQZ9PO8-flwwRtEppYTS0OjA",
                              "board": null,
                              "country_code": null,
                              "is_ad": false,
                              "is_ai_generated": true,
                              "location": null,
                              "music": {
                                "author_name": "Khabane lame",
                                "cover_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/08987e23b94057953fd4f1738694bf5f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=07918010&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 34000,
                                "id": "7691740326570019615",
                                "is_original": true,
                                "play_url": "https://v16-webapp-prime.us.tiktok.com/video/tos/useast8/tos-useast8-v-27dcd7-tx2/ogcDFBGWoU0A8F0eIAAREf8XVjvDqICFsEDJAo/?a=1988&bti=ODszNWYuMDE6&&bt=125&ft=GcAInInz7Th~v-RGXq8Zmo&mime_type=audio_mpeg&rc=M3hmanQ5cjg7ZDMzaTU8NEBpM3hmanQ5cjg7ZDMzaTU8NEBjMGgyMmRzbnNhLS1kMTJzYSNjMGgy…",
                                "title": "original sound"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-01T16:40:54Z",
                          "text": "Just give me 5 more minutes 😭#learnfromkhaby #comedy",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/o0jRDQRMAbfFAlZX8eqGQcARBqerRfAHR7gVSU~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@khaby.lame/video/7691740195418377502"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 888,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "127905465618821121",
                          "url": "https://www.tiktok.com/@khaby.lame"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokPostsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Account videos and photo posts, newest first",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "page_max": 15,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/profile": {
      "get": {
        "description": "Returns a public TikTok profile from a username, profile link, user ID or secUid, with exact follower, following, video and like counts. It also has the display name, bio, bio link, avatar, verified badge, user ID and secUid, whether the account is private, its business category, join date and registered country.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/profile/ (Markdown: https://socialtap.dev/docs/reference/tiktok/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/profile/"
        },
        "operationId": "tiktok.profile.get",
        "parameters": [
          {
            "description": "TikTok username with or without the @ (nasa, @nasa), a profile URL (tiktok.com/@nasa, m.tiktok.com/@nasa, with or without query parameters), a numeric user ID (tiktok.com/share/user/<id> or the bare ID), or a secUid (MS4wLjABAAAA…). Usernames are case-insensitive.",
            "example": "nasa",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "TikTok username with or without the @ (nasa, @nasa), a profile URL (tiktok.com/@nasa, m.tiktok.com/@nasa, with or without query parameters), a numeric user ID (tiktok.com/share/user/<id> or the bare ID), or a secUid (MS4wLjABAAAA…). Usernames are case-insensitive.",
              "examples": [
                "nasa"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/e5143212a59c09a008bf50f487d54d1f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=29840d4e&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                        "banner_url": null,
                        "bio": "Making the seemingly impossible, possible.✨",
                        "category": null,
                        "country_code": "US",
                        "created_at": "2026-07-20T15:55:49Z",
                        "display_name": "NASA",
                        "external_links": [
                          {
                            "title": null,
                            "url": "https://science.nasa.gov/feature/artemis-ii-preliminary-lunar-science-report"
                          }
                        ],
                        "id": "7664638705177150477",
                        "is_private": false,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 2152843,
                          "following_count": 23,
                          "post_count": 62,
                          "total_like_count": 11486661,
                          "total_view_count": null
                        },
                        "platform": "tiktok",
                        "platform_specific": {
                          "tiktok": {
                            "display_name_changed_at": "2026-07-20T15:58:00Z",
                            "friend_count": 17,
                            "is_business_account": false,
                            "is_shop_seller": false,
                            "language": "en",
                            "liked_post_count": null,
                            "sec_uid": "MS4wLjABAAAAU9BRVzC8oCaegVnia8IbqWhPb_-dbU7s00Y3wS1_Nx8g5RUaYvyXrpejgjdxTwd6"
                          }
                        },
                        "type": "organization",
                        "unknown_fields": [],
                        "url": "https://www.tiktok.com/@nasa",
                        "username": "nasa"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1098,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "7664638705177150477",
                          "url": "https://www.tiktok.com/@nasa"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact follower and like counts, bio and country",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/replies": {
      "get": {
        "description": "Returns the public replies to a top-level comment on a TikTok video or photo post, a page at a time. Each reply has its text, exact posting time and like count, the replier's username, name, ID and verified badge, its language, the comment it answers, and whether the creator wrote or liked it. Send a comment link, or the post's link and comment_id.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Comment` items (the shared schema, the same on every platform), TikTok's reply order (the order its app shows: a reply to a reply follows the one it answers). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/replies/ (Markdown: https://socialtap.dev/docs/reference/tiktok/replies/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/replies/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/replies/"
        },
        "operationId": "tiktok.replies.list",
        "parameters": [
          {
            "description": "The TikTok video or photo post the comment is on: a tiktok.com/@user/video/<id> or /@user/photo/<id> link, m.tiktok.com/v/<id>.html, embed and player URLs, vm.tiktok.com/<code>, vt.tiktok.com/<code>, tiktok.com/t/<code> or a numeric video ID; or a comment link (TikTok's comment share link with share_comment_id, or a video link with comment_id), which names the comment too.",
            "example": "https://www.tiktok.com/@scout2015/video/6718335390845095173",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The TikTok video or photo post the comment is on: a tiktok.com/@user/video/<id> or /@user/photo/<id> link, m.tiktok.com/v/<id>.html, embed and player URLs, vm.tiktok.com/<code>, vt.tiktok.com/<code>, tiktok.com/t/<code> or a numeric video ID; or a comment link (TikTok's comment share link with share_comment_id, or a video link with comment_id), which names the comment too.",
              "examples": [
                "https://www.tiktok.com/@scout2015/video/6718335390845095173"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "ID of the top-level comment whose replies to list (the id of a TikTok comment; a reply's thread_id names its top-level comment). Required unless url is a comment link.",
            "example": "6718335906996502534",
            "in": "query",
            "name": "comment_id",
            "schema": {
              "description": "ID of the top-level comment whose replies to list (the id of a TikTok comment; a reply's thread_id names its top-level comment). Required unless url is a comment link.",
              "examples": [
                "6718335906996502534"
              ],
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/0a9840d173e7d6ec0862b3e444c198b7~tplv-tiktokx-cropcenter:100:100.jpg?dr=9640&refresh_token=6a787626&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=30310797&shcp=ff37627b&idc=useast5",
                            "display_name": "💫marladraws💫",
                            "id": "6654948959952060422",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@marladraws",
                            "username": "marladraws"
                          },
                          "edited_at": null,
                          "id": "6718605798119555078",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": false,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": 0,
                            "reply_count": null
                          },
                          "parent_id": "6718335906996502534",
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_sec_uid": null,
                              "language": null,
                              "thread_id": "6718335906996502534"
                            }
                          },
                          "post_id": "6718335390845095173",
                          "published_at": "2019-07-28T07:01:56Z",
                          "text": "dorotea?",
                          "unknown_fields": [],
                          "url": "https://m.tiktok.com/v/6718335390845095173.html?share_comment_id=6718605798119555078&share_item_id=6718335390845095173"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/7336370956674203653~tplv-tiktokx-cropcenter:100:100.jpg?dr=9640&refresh_token=97c80bf2&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=30310797&shcp=ff37627b&idc=useast5",
                            "display_name": "flamigoo",
                            "id": "6650133637952618502",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@flamigo_kisses",
                            "username": "flamigo_kisses"
                          },
                          "edited_at": null,
                          "id": "6718648089844400133",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": false,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": 2,
                            "reply_count": null
                          },
                          "parent_id": "6718605798119555078",
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_sec_uid": null,
                              "language": null,
                              "thread_id": "6718335906996502534"
                            }
                          },
                          "post_id": "6718335390845095173",
                          "published_at": "2019-07-28T09:46:01Z",
                          "text": "yes!",
                          "unknown_fields": [],
                          "url": "https://m.tiktok.com/v/6718335390845095173.html?share_comment_id=6718648089844400133&share_item_id=6718335390845095173"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/465a2c1b56c92945eb7a02f98e51ff3f~tplv-tiktokx-cropcenter:100:100.jpg?dr=9640&refresh_token=7f288ca7&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=30310797&shcp=ff37627b&idc=useast5",
                            "display_name": "ivana.ckc",
                            "id": "6615151770753613829",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@ivana.ckc",
                            "username": "ivana.ckc"
                          },
                          "edited_at": null,
                          "id": "6718414854476709893",
                          "is_by_post_author": false,
                          "is_edited": null,
                          "is_liked_by_author": false,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": 1,
                            "reply_count": null
                          },
                          "parent_id": "6718335906996502534",
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_sec_uid": null,
                              "language": null,
                              "thread_id": "6718335906996502534"
                            }
                          },
                          "post_id": "6718335390845095173",
                          "published_at": "2019-07-27T18:40:56Z",
                          "text": "Dorotea! Kako si? Neznam tebe ali hocu da znam😂",
                          "unknown_fields": [],
                          "url": "https://m.tiktok.com/v/6718335390845095173.html?share_comment_id=6718414854476709893&share_item_id=6718335390845095173"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 345,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "6718335390845095173",
                          "url": "https://www.tiktok.com/@/video/6718335390845095173"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokRepliesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Thread under a comment, with likes and authors",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.replies",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "TikTok's reply order (the order its app shows: a reply to a reply follows the one it answers)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/search_ads": {
      "get": {
        "description": "Searches TikTok's public ad library, which holds ads shown in Europe, by keyword, exact phrase or advertiser, a page at a time. Each ad has its advertiser, text, media, the days it ran, reach, topic and any takedown. Filter by country, active or inactive and date, and sort by relevance, newest, oldest or popularity.\n\nReturns `{data, page, meta}`: `data` holds up to 12 `Ad` items (the shared schema, the same on every platform), relevance (keywords) or newest with sort=relevance (the default), last shown, newest first with sort=newest, last shown, oldest first with sort=oldest, most unique users first with sort=popular. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/search_ads/ (Markdown: https://socialtap.dev/docs/reference/tiktok/search_ads/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/search_ads/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/search_ads/"
        },
        "operationId": "tiktok.search_ads.list",
        "parameters": [
          {
            "description": "Keywords, a \"quoted phrase\", or (search_by=advertiser) an advertiser's name.",
            "example": "coffee",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Keywords, a \"quoted phrase\", or (search_by=advertiser) an advertiser's name.",
              "examples": [
                "coffee"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "advertiser: the advertiser named exactly as query, else TikTok's first suggestion.",
            "example": "",
            "in": "query",
            "name": "search_by",
            "schema": {
              "default": "keyword",
              "description": "advertiser: the advertiser named exactly as query, else TikTok's first suggestion.",
              "enum": [
                "keyword",
                "advertiser"
              ],
              "type": "string"
            }
          },
          {
            "description": "An advertiser's business ID (platform_specific.tiktok.advertiser_business_id), with query its name.",
            "example": "7413374016335134736",
            "in": "query",
            "name": "advertiser_id",
            "schema": {
              "description": "An advertiser's business ID (platform_specific.tiktok.advertiser_business_id), with query its name.",
              "examples": [
                "7413374016335134736"
              ],
              "pattern": "^[0-9]{6,24}(,[0-9]{6,24})*$",
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive).",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive).",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items that are still running (active), only items that stopped (inactive), or both (all).",
            "example": "active",
            "in": "query",
            "name": "status",
            "schema": {
              "default": "all",
              "description": "Only items that are still running (active), only items that stopped (inactive), or both (all).",
              "enum": [
                "active",
                "inactive",
                "all"
              ],
              "examples": [
                "active"
              ],
              "type": "string"
            }
          },
          {
            "description": "Order of the results. Keywords rank by relevance first.",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "relevance",
              "description": "Order of the results. Keywords rank by relevance first.",
              "enum": [
                "relevance",
                "newest",
                "oldest",
                "popular"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 12,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 12,
              "maximum": 12,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "advertiser": {
                            "avatar_url": null,
                            "display_name": "raisedinluxury",
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "approximate_fields": [
                            "first_shown_at",
                            "last_shown_at",
                            "reach"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": "Mushroom coffee #coffee",
                              "cta_text": null,
                              "link_description": null,
                              "link_url": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": null,
                                  "height": null,
                                  "thumbnail_url": "https://p16-common-sign.tiktokcdn.com/tos-alisg-p-37c799-sg/o8UknFBVVDq0iQCOhAzGAS2tQfwxmfEEd3QRkE~tplv-noop.image?dr=18692&refresh_token=d75541c5&x-expires=4070908800&x-signature=SCRUBBED&t=9276707c&ps=14f1eb3e&shp=9e36835a&shcp=0c75dd76&idc=sg1&VideoID=v15025gf0000da547cfog65jp…",
                                  "type": "video",
                                  "url": "https://library.tiktok.com/api/v1/cdn/1793574003/video/aHR0cHM6Ly92NzcudGlrdG9rY2RuLmNvbS8yNzFmNGQ5MDI5ZjE0Y2M0M2IxYTU4MWNlNGZjN2EyZi82YWU4MThlNy92aWRlby90b3MvYWxpc2cvdG9zLWFsaXNnLXZlLTM3Yzc5OS1zZy9vWUlyUktBMVJSS1FIaVdvelNxQjlBUUJxNGlmQVl6VUlFRURpUy8=/e4ffaaa5-2a8f-4350-8715-b93e…",
                                  "width": null
                                }
                              ],
                              "title": null
                            }
                          ],
                          "first_shown_at": "2026-08-23T00:00:00Z",
                          "id": "1874320211952658",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": "2026-08-23T00:00:00Z",
                          "paid_by": null,
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "advertiser_business_id": null,
                              "advertiser_registry_location": null,
                              "budget": null,
                              "category": null,
                              "ctr_top_percent": null,
                              "is_removed": false,
                              "like_count": null,
                              "objective": null,
                              "rank": null,
                              "removal_country_codes": [],
                              "removal_reasons": [],
                              "targeting": null
                            }
                          },
                          "publisher_platforms": [
                            "tiktok"
                          ],
                          "reach": {
                            "lower_bound": 0,
                            "upper_bound": 1000
                          },
                          "spend": null,
                          "type": "video",
                          "unknown_fields": [
                            "country_codes"
                          ],
                          "url": "https://library.tiktok.com/ads/detail/?ad_id=1874320211952658"
                        },
                        {
                          "advertiser": {
                            "avatar_url": null,
                            "display_name": "Manea Coffee",
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "approximate_fields": [
                            "first_shown_at",
                            "last_shown_at",
                            "reach"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": "Caja de muestras | Manea Coffee",
                              "cta_text": null,
                              "link_description": null,
                              "link_url": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": null,
                                  "height": null,
                                  "thumbnail_url": "https://p16-common-sign.tiktokcdn.com/tos-alisg-p-0051c001-sg/o0QMomDeZefhMFgshsbGeqxAQBA4NRQIDA8W2C~tplv-tiktokx-origin.jpeg?dr=14582&refresh_token=3d9c5080&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=0c75dd76&shcp=9b759fb9&idc=sg1",
                                  "type": "video",
                                  "url": "https://library.tiktok.com/api/v1/cdn/1793574003/video/aHR0cHM6Ly92NzcudGlrdG9rY2RuLmNvbS84NjM5ZjgxN2VlZTkzMzk2N2U2YjgzNjY3YzE3ZGNlNy82YWU4MThmNi92aWRlby90b3MvdXNlYXN0MmEvdG9zLXVzZWFzdDJhLXZlLTAwNTFjNzk5LWV1dHRwL293VEF3Q0VRZDRERWJGQUl0V0xWRnNtRGZ2Z1FnVUVHaGZJZkI3Lw==/2683c39b-6f1…",
                                  "width": null
                                }
                              ],
                              "title": null
                            }
                          ],
                          "first_shown_at": "2026-06-08T00:00:00Z",
                          "id": "1867421334452290",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": "2026-06-19T00:00:00Z",
                          "paid_by": null,
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "advertiser_business_id": null,
                              "advertiser_registry_location": null,
                              "budget": null,
                              "category": null,
                              "ctr_top_percent": null,
                              "is_removed": false,
                              "like_count": null,
                              "objective": null,
                              "rank": null,
                              "removal_country_codes": [],
                              "removal_reasons": [],
                              "targeting": null
                            }
                          },
                          "publisher_platforms": [
                            "tiktok"
                          ],
                          "reach": {
                            "lower_bound": 1000,
                            "upper_bound": 10000
                          },
                          "spend": null,
                          "type": "video",
                          "unknown_fields": [
                            "country_codes"
                          ],
                          "url": "https://library.tiktok.com/ads/detail/?ad_id=1867421334452290"
                        },
                        {
                          "advertiser": {
                            "avatar_url": null,
                            "display_name": "Manea Coffee",
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "approximate_fields": [
                            "first_shown_at",
                            "last_shown_at",
                            "reach"
                          ],
                          "audience_size": null,
                          "country_codes": [],
                          "creatives": [
                            {
                              "body": "Caja de muestras | Manea Coffee",
                              "cta_text": null,
                              "link_description": null,
                              "link_url": null,
                              "media": [],
                              "title": null
                            }
                          ],
                          "first_shown_at": "2026-06-08T00:00:00Z",
                          "id": "1867423264630914",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": "2026-06-09T00:00:00Z",
                          "paid_by": null,
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "advertiser_business_id": null,
                              "advertiser_registry_location": null,
                              "budget": null,
                              "category": null,
                              "ctr_top_percent": null,
                              "is_removed": false,
                              "like_count": null,
                              "objective": null,
                              "rank": null,
                              "removal_country_codes": [],
                              "removal_reasons": [],
                              "targeting": null
                            }
                          },
                          "publisher_platforms": [
                            "tiktok"
                          ],
                          "reach": {
                            "lower_bound": 0,
                            "upper_bound": 1000
                          },
                          "spend": null,
                          "type": "image",
                          "unknown_fields": [
                            "country_codes"
                          ],
                          "url": "https://library.tiktok.com/ads/detail/?ad_id=1867423264630914"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 2510,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokSearch_adsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Ads by keyword or advertiser, with reach",
        "tags": [
          "TikTok Ad Library"
        ],
        "x-socialtap-endpoint": "tiktok.search_ads",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "relevance (keywords) or newest",
          "orders": {
            "newest": "last shown, newest first",
            "oldest": "last shown, oldest first",
            "popular": "most unique users first",
            "relevance": "relevance (keywords) or newest"
          },
          "page_max": 12,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "ad",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/search_hashtags": {
      "get": {
        "description": "Returns the TikTok hashtags a web search finds for your words, each with its name and link, a page at a time. Its post count and TikTok's description of it come too when the search index shows them. Add fill=true to also get each hashtag's full live record (its ID, exact post and view counts, picture) in the same response.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/search_hashtags/ (Markdown: https://socialtap.dev/docs/reference/tiktok/search_hashtags/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/search_hashtags/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/search_hashtags/"
        },
        "operationId": "tiktok.search_hashtags.list",
        "parameters": [
          {
            "description": "Words to find TikTok hashtags by, as a web search reads them: a topic, a niche, a community (cooking, home gym, \"meal prep\"). A leading # is dropped, quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint.",
            "example": "cooking",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find TikTok hashtags by, as a web search reads them: a topic, a niche, a community (cooking, home gym, \"meal prep\"). A leading # is dropped, quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint.",
              "examples": [
                "cooking"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": {
                            "description": null,
                            "id": null,
                            "metrics": {
                              "post_count": null
                            },
                            "name": "cooking",
                            "thumbnail_url": null,
                            "url": "https://www.tiktok.com/tag/cooking"
                          },
                          "matched_url": "https://www.tiktok.com/tag/cooking",
                          "place": null,
                          "platform": "tiktok",
                          "platform_specific": {},
                          "position": 0,
                          "post": null,
                          "profile": null,
                          "snippet": "Everyone is cooking rice like this after seeing this genius idea #cooking #recipe #easyrecipe #quickrecipes #cook #chocolate #cake #dessert #viral #viraltiktok",
                          "sound": null,
                          "title": "#cooking | TikTok",
                          "type": "hashtag",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/tag/cooking"
                        },
                        {
                          "approximate_fields": [
                            "hashtag.metrics.post_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": {
                            "description": null,
                            "id": null,
                            "metrics": {
                              "post_count": 246100
                            },
                            "name": "cookingvideos",
                            "thumbnail_url": null,
                            "url": "https://www.tiktok.com/tag/cookingvideos"
                          },
                          "matched_url": "https://www.tiktok.com/tag/cookingvideos",
                          "place": null,
                          "platform": "tiktok",
                          "platform_specific": {},
                          "position": 1,
                          "post": null,
                          "profile": null,
                          "snippet": "cooking videos | 246.1K posts Watch the latest videos about #cookingvideos on TikTok.",
                          "sound": null,
                          "title": "#cookingvideos | TikTok",
                          "type": "hashtag",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/tag/cookingvideos"
                        },
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": {
                            "description": null,
                            "id": null,
                            "metrics": {
                              "post_count": null
                            },
                            "name": "kochen",
                            "thumbnail_url": null,
                            "url": "https://www.tiktok.com/tag/kochen"
                          },
                          "matched_url": "https://www.tiktok.com/tag/kochen",
                          "place": null,
                          "platform": "tiktok",
                          "platform_specific": {},
                          "position": 2,
                          "post": null,
                          "profile": null,
                          "snippet": "Bei mir gibt es die schnellsten, leckersten und gesündesten Frühstücke😉 #cooking #kochen #frühstück #foodtok",
                          "sound": null,
                          "title": "#kochen | TikTok",
                          "type": "hashtag",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/tag/kochen"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1188,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokSearch_hashtagsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Hashtags for a keyword, topic or niche",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.search_hashtags",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/search_posts": {
      "get": {
        "description": "Returns TikTok videos for a keyword, a page at a time, in TikTok's relevance order for a country. Each has its caption, hashtags, mentions, publish time, duration, cover, sound, engagement counts and author with the verification badge.\n\nReturns `{data, page, meta}`: `data` holds up to 30 `Post` items (the shared schema, the same on every platform), TikTok's relevance order for the keyword. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/search_posts/ (Markdown: https://socialtap.dev/docs/reference/tiktok/search_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/search_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/search_posts/"
        },
        "operationId": "tiktok.search_posts.list",
        "parameters": [
          {
            "description": "Keywords: TikTok's videos for them, as its Discover page for the words shows them (case, a leading # or @ and punctuation ending a word are ignored).",
            "example": "cooking",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Keywords: TikTok's videos for them, as its Discover page for the words shows them (case, a leading # or @ and punctuation ending a word are ignored).",
              "examples": [
                "cooking"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The region whose results to return: TikTok ranks a keyword's videos per country (US by default).",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "default": "US",
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The region whose results to return: TikTok ranks a keyword's videos per country (US by default).",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 30,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 30,
              "maximum": 30,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count"
                          ],
                          "author": {
                            "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/aca82868240f752191e7097098eb0732~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=594acaa3&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Lazy Pot Noodle🍜",
                            "id": "7222034441425634347",
                            "is_verified": true,
                            "url": "https://www.tiktok.com/@lazypotnoodle",
                            "username": "lazypotnoodle"
                          },
                          "coauthors": [],
                          "duration_ms": 77000,
                          "hashtags": [
                            "food",
                            "pasta",
                            "easyrecipe"
                          ],
                          "id": "7695425484204559647",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 77000,
                              "expires_at": null,
                              "height": 1280,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/ooPEnf6LRAiRDJUIEvfEAVBVpEyFIIP1qVR71T~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=0d52deaf&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 498,
                            "like_count": 82200,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 11124,
                            "share_count": 3315,
                            "view_count": 1100000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAcqFqHEsjs6cgthDQjY048KO4PI1hvtY5Sk9T-dd3eDAzX5c_Xov-tRgk-rxXZ_Qc",
                              "board": null,
                              "country_code": null,
                              "is_ad": null,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "Lazy Pot Noodle🍜",
                                "cover_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/aca82868240f752191e7097098eb0732~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=594acaa3&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 77000,
                                "id": "7695425757970959134",
                                "is_original": false,
                                "play_url": "https://v16m.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast8/tos-useast8-v-27dcd7-tx2/oAAQAQxATneQVEk8uAglM0eFcnAMoCWpqFnIew/?a=1233&bti=ODszNWYuMDE6&&bt=125&ft=GSDrKInz7ThG4tyGXq8Zmo&mime_type=audio_mpeg&rc=Mzx4ZHA5cnd0ZTMzaTU8NEBpMzx4ZHA5cnd0ZTMzaTU8NEBwbHAxMmQ0NjJhLS1kMTJ…",
                                "title": "original sound"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-11T15:02:10Z",
                          "text": "Making Cajun Shrimp & Sausage pasta in my room! 🦐🤤 — I would make this everyday if I could. Pretty much a one pot meal! What should I make for Halloween? 👀  Order Lazy Pot on Amazon! Ingredients: * Cajun sausage * Medium shrimp, peeled and deveined, tails removed * Salt * Black p…",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/ooPEnf6LRAiRDJUIEvfEAVBVpEyFIIP1qVR71T~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=0d52deaf&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@lazypotnoodle/video/7695425484204559647"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count"
                          ],
                          "author": {
                            "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/7352667004160966699~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=28e75743&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "cooking_recipescr",
                            "id": "7352666564073833515",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@cooking_recipescr",
                            "username": "cooking_recipescr"
                          },
                          "coauthors": [],
                          "duration_ms": 1435000,
                          "hashtags": [
                            "recipes",
                            "easyrecipe",
                            "cooking"
                          ],
                          "id": "7692609313717636383",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 1435000,
                              "expires_at": null,
                              "height": 1282,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-85c255-tx2/oYIODVIg8C09xADHLrQJGLIIVRGqfgCfge4Buq~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=0d52deaf&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 483,
                            "like_count": 23500,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 14331,
                            "share_count": 8120,
                            "view_count": 1400000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAA9RLA_aJw3o-9lGAAgNdwVqfTMqakk-crm46C_kbbWjvl_QJw-j5GzmOZ0hNY1nDt",
                              "board": null,
                              "country_code": null,
                              "is_ad": null,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "cooking_recipescr",
                                "cover_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/7352667004160966699~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=28e75743&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 1420000,
                                "id": "7692609536951110431",
                                "is_original": false,
                                "play_url": "https://v19.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast8/tos-useast8-v-27dcd7-tx2/ocCE6YiD1AL7cBq6KCHTotAEBfBwiiAHzAA1NE/?a=1233&bti=ODszNWYuMDE6&&bt=125&ft=GSDrKInz7ThG4tyGXq8Zmo&mime_type=audio_mpeg&rc=MzpxanQ5cjx0ZTMzaTU8NEBpMzpxanQ5cjx0ZTMzaTU8NEAuM2oyMmRzNC1hLS1kMTJz…",
                                "title": "original sound"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-04T00:49:32Z",
                          "text": "#recipes #easyrecipe #cooking #dinnerideas",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-85c255-tx2/oYIODVIg8C09xADHLrQJGLIIVRGqfgCfge4Buq~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=0d52deaf&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@cooking_recipescr/video/7692609313717636383"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count",
                            "metrics.share_count"
                          ],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/777f804c7ef139295f9b8cb14407a4e0~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=bc3e4267&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Bill | Food In Five",
                            "id": "7096148302610203653",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@foodinfivemins",
                            "username": "foodinfivemins"
                          },
                          "coauthors": [],
                          "duration_ms": 36000,
                          "hashtags": [
                            "easyrecipes",
                            "healthyfood",
                            "dinnerideas"
                          ],
                          "id": "7693497065078312214",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 36000,
                              "expires_at": null,
                              "height": 1024,
                              "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-no1a-p-0037-no/o4HJdRAieAgSVTOT7GjVdcDglILILI0S7Zegfi~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=0d52deaf&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 576
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 757,
                            "like_count": 201100,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 181324,
                            "share_count": 53300,
                            "view_count": 4700000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAoEugba63vfXpr67KCK19OnbZ6G7eysLdH47Vbja_7peS-lJMl4mpqJVMGsWFi5uJ",
                              "board": null,
                              "country_code": null,
                              "is_ad": null,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "TheJointDowney",
                                "cover_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/23b2da781b1ec1aa5c11d1e1bdf9471c~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=772f2451&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 60000,
                                "id": "7642807113445624589",
                                "is_original": false,
                                "play_url": "https://v16m.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast5/tos-useast5-v-27dcd7-tx/o8hKQCfqLSAJFEEqAEFfDBgN4tLASNEsJAD7Ui/?a=1233&bti=ODszNWYuMDE6&&bt=125&ft=GSDrKInz7ThG4tyGXq8Zmo&mime_type=audio_mpeg&rc=anJlN3c5cjtlOzMzZzU8NEBpanJlN3c5cjtlOzMzZzU8NEAzczFvMmRrNjVhLS1kMS9z…",
                                "title": "original sound"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-06T10:18:05Z",
                          "text": "Garlic lemon chicken with green beans & sweet potato mash 🍠  You can find the full written recipe on my Recipe Portal 🙌 Macros per serve: 35g protein 44g fat 61g carbs 10g fibre per serve 🫘  777 calories per serve 💪  Ingredients for 3 portions: For the chicken 🍋  5 Chicken Thight…",
                          "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-no1a-p-0037-no/o4HJdRAieAgSVTOT7GjVdcDglILILI0S7Zegfi~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=0d52deaf&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@foodinfivemins/video/7693497065078312214"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1329,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokSearch_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Videos for a keyword, by country",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.search_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "TikTok's relevance order for the keyword",
          "page_max": 30,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/search_profiles": {
      "get": {
        "description": "Returns the TikTok accounts a web search finds for your words, each with its username and profile link, a page at a time. Its display name, bio and follower, following and like counts come too, as the search index shows them. Add fill=true to also get each account's full live profile (user ID, exact counts, verification, avatar) in the same response.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/search_profiles/ (Markdown: https://socialtap.dev/docs/reference/tiktok/search_profiles/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/search_profiles/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/search_profiles/"
        },
        "operationId": "tiktok.search_profiles.list",
        "parameters": [
          {
            "description": "Words to find TikTok accounts by, as a web search reads them: a niche, a business type, a place, a name (barber, yoga studio austin, \"wine bar\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint.",
            "example": "barber",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find TikTok accounts by, as a web search reads them: a niche, a business type, a place, a name (barber, yoga studio austin, \"wine bar\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint.",
              "examples": [
                "barber"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "profile.bio",
                            "profile.metrics.follower_count",
                            "profile.metrics.following_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.tiktok.com/@barberhouse03",
                          "place": null,
                          "platform": "tiktok",
                          "platform_specific": {},
                          "position": 0,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "💈DEJA DE SER UN PRINCIPIANTE 💈 👌🏻COBRA LO QUE MERECES POR TU LABOR👌🏻 ↘️↘️ACCEDE CON EL 50% OFF AQUÍ ↙️↙️ · barberhousedigital.netlify.app/",
                            "display_name": "BARBERHOUSE 💈",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": 1400000,
                              "following_count": 12,
                              "post_count": null,
                              "total_like_count": 9100000,
                              "total_view_count": null
                            },
                            "url": "https://www.tiktok.com/@barberhouse03",
                            "username": "barberhouse03"
                          },
                          "snippet": "BARBERHOUSE 💈 · barberhouse03 · 12Following · 1.4MFollowers · 9.1MLikes · 💈DEJA DE SER UN PRINCIPIANTE 💈 👌🏻COBRA LO QUE MERECES POR TU LABOR👌🏻 ↘️↘️ACCEDE CON EL 50% OFF AQUÍ ↙️↙️ · barberhousedigital.netlify.app/",
                          "sound": null,
                          "title": "BARBERHOUSE 💈 (@barberhouse03)",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@barberhouse03"
                        },
                        {
                          "approximate_fields": [
                            "profile.bio",
                            "profile.metrics.follower_count",
                            "profile.metrics.total_like_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.tiktok.com/@barbaros.barber",
                          "place": null,
                          "platform": "tiktok",
                          "platform_specific": {},
                          "position": 1,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "Barbería en san Miguel 📍💈 Agenda tu hora con nosotros! ⬇️⬇️⬇️⬇️",
                            "display_name": "Bárbaros Barberia💈",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": 11400,
                              "following_count": null,
                              "post_count": null,
                              "total_like_count": 55100,
                              "total_view_count": null
                            },
                            "url": "https://www.tiktok.com/@barbaros.barber",
                            "username": "barbaros.barber"
                          },
                          "snippet": "Bárbaros Barberia💈 (@barbaros.barber) on TikTok | 55.1K Likes. 11.4K Followers. Barbería en san Miguel 📍💈 Agenda tu hora con nosotros! ⬇️⬇️⬇️⬇️.Watch Bárbaros Barberia💈's popular videos: \"Las risas en barbaro...\", \"Ayuden a etiquetarlo...\". Join 11.4K followers on TikTok for more…",
                          "sound": null,
                          "title": "Bárbaros Barberia💈 (@barbaros.barber) | TikTok",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@barbaros.barber"
                        },
                        {
                          "approximate_fields": [
                            "profile.bio",
                            "profile.metrics.follower_count",
                            "profile.metrics.following_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.tiktok.com/@sambarber_music",
                          "place": null,
                          "platform": "tiktok",
                          "platform_specific": {},
                          "position": 2,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "Singer/Songwriter “Broken View” out now · bio.to/SamBarber",
                            "display_name": "Sam Barber",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": 1400000,
                              "following_count": 202,
                              "post_count": null,
                              "total_like_count": 19800000,
                              "total_view_count": null
                            },
                            "url": "https://www.tiktok.com/@sambarber_music",
                            "username": "sambarber_music"
                          },
                          "snippet": "Sam Barber · sambarber_music · 202Following · 1.4MFollowers · 19.8MLikes · Singer/Songwriter “Broken View” out now · bio.to/SamBarber · Log in",
                          "sound": null,
                          "title": "Sam Barber (@sambarber_music)",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@sambarber_music"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1280,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokSearch_profilesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Accounts by keyword, niche or place",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.search_profiles",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/search_sounds": {
      "get": {
        "description": "Returns the TikTok sounds a web search finds for a song title, artist or keyword, each with its link, a page at a time. Its title, artist or creator and video count come too, as the search index shows them. Add fill=true to also get each sound's full live record (sound ID, duration, cover art, audio link, album, exact video count) in the same response.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/search_sounds/ (Markdown: https://socialtap.dev/docs/reference/tiktok/search_sounds/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/search_sounds/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/search_sounds/"
        },
        "operationId": "tiktok.search_sounds.list",
        "parameters": [
          {
            "description": "Words to find TikTok sounds by, as a web search reads them: a song, an artist, a mood (taylor swift, lofi, \"cruel summer\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint.",
            "example": "Taylor Swift",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find TikTok sounds by, as a web search reads them: a song, an artist, a mood (taylor swift, lofi, \"cruel summer\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint.",
              "examples": [
                "taylor swift"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "sound.metrics.post_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.tiktok.com/music/Style-6792322634764781569",
                          "place": null,
                          "platform": "tiktok",
                          "platform_specific": {},
                          "position": 0,
                          "post": null,
                          "profile": null,
                          "snippet": "Style song created by Taylor Swift. 121.5K videos. Watch the latest videos about Style on TikTok.",
                          "sound": {
                            "author_name": "Taylor Swift",
                            "cover_url": null,
                            "id": null,
                            "is_original": null,
                            "metrics": {
                              "post_count": 121500
                            },
                            "title": "Style",
                            "url": "https://www.tiktok.com/music/-6792322634764781569"
                          },
                          "title": "Taylor Swift - Style | TikTok",
                          "type": "sound",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/music/-6792322634764781569"
                        },
                        {
                          "approximate_fields": [
                            "sound.metrics.post_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.tiktok.com/music/Style-Taylor's-Version-7294449191711197186",
                          "place": null,
                          "platform": "tiktok",
                          "platform_specific": {},
                          "position": 1,
                          "post": null,
                          "profile": null,
                          "snippet": "Style (Taylor's Version) song created by Taylor Swift. 820.1K videos. Watch the latest videos about Style (Taylor's Version) on TikTok.",
                          "sound": {
                            "author_name": "Taylor Swift",
                            "cover_url": null,
                            "id": null,
                            "is_original": null,
                            "metrics": {
                              "post_count": 820100
                            },
                            "title": "Style (Taylor's Version)",
                            "url": "https://www.tiktok.com/music/-7294449191711197186"
                          },
                          "title": "Taylor Swift - Style (Taylor's Version) | TikTok",
                          "type": "sound",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/music/-7294449191711197186"
                        },
                        {
                          "approximate_fields": [
                            "sound.metrics.post_count"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.tiktok.com/music/Ready-For-It-6752003161755486209",
                          "place": null,
                          "platform": "tiktok",
                          "platform_specific": {},
                          "position": 2,
                          "post": null,
                          "profile": null,
                          "snippet": "...Ready For It? song created by Taylor Swift. 177.3K videos. Watch the latest videos about ...Ready For It? on TikTok.",
                          "sound": {
                            "author_name": "Taylor Swift",
                            "cover_url": null,
                            "id": null,
                            "is_original": null,
                            "metrics": {
                              "post_count": 177300
                            },
                            "title": "...Ready For It?",
                            "url": "https://www.tiktok.com/music/-6752003161755486209"
                          },
                          "title": "Taylor Swift - ...Ready For It? | TikTok",
                          "type": "sound",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/music/-6752003161755486209"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1139,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokSearch_soundsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Sounds and songs by title, artist or keyword",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.search_sounds",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/search_suggestions": {
      "get": {
        "description": "Returns the searches TikTok's search box completes a partial query to, in TikTok's order, from a word, part of a word or a name. Each suggestion has its text, rank, language, TikTok's predicted click rate and a link to its results. An account TikTok proposes comes with its user ID, username, display name, picture and verified badge. Set country to get what people there search.\n\nReturns `{data, page, meta}`: `data` holds up to 20 `Suggestion` items (the shared schema, the same on every platform), TikTok's search box order (most likely search first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/search_suggestions/ (Markdown: https://socialtap.dev/docs/reference/tiktok/search_suggestions/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/search_suggestions/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/search_suggestions/"
        },
        "operationId": "tiktok.search_suggestions.list",
        "parameters": [
          {
            "description": "The start of a search, as typed into TikTok's search box: a word, part of a word, a name or a username, in any language (cook, taylor sw, 料理). Capitals are kept, since TikTok orders suggestions by them.",
            "example": "cook",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "The start of a search, as typed into TikTok's search box: a word, part of a word, a name or a username, in any language (cook, taylor sw, 料理). Capitals are kept, since TikTok orders suggestions by them.",
              "examples": [
                "cook"
              ],
              "maxLength": 150,
              "type": "string"
            }
          },
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The country whose suggestions to return: TikTok completes a search with what people there look for (rec gives recipes in the US and receitas in BR). One of US, GB, CA, AU, BR, MX, ES, DE, FR, IT, NL, PL, TR, ID, JP (case-insensitive). Default: US.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "default": "US",
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The country whose suggestions to return: TikTok completes a search with what people there look for (rec gives recipes in the US and receitas in BR). One of US, GB, CA, AU, BR, MX, ES, DE, FR, IT, NL, PL, TR, ID, JP (case-insensitive). Default: US.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 20,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "hashtag": null,
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "language": "en",
                              "score": 0.0033766124
                            }
                          },
                          "position": 0,
                          "profile": null,
                          "text": "cooking big hyatt",
                          "type": "query",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/search?q=cooking+big+hyatt"
                        },
                        {
                          "approximate_fields": [],
                          "hashtag": null,
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "language": "en",
                              "score": 0.025226826
                            }
                          },
                          "position": 1,
                          "profile": null,
                          "text": "cooking with kya",
                          "type": "query",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/search?q=cooking+with+kya"
                        },
                        {
                          "approximate_fields": [],
                          "hashtag": null,
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "language": "en",
                              "score": 0.0131212715
                            }
                          },
                          "position": 2,
                          "profile": null,
                          "text": "cooking food videos",
                          "type": "query",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/search?q=cooking+food+videos"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 0,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokSearch_suggestionsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Search box autocomplete for a partial query",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.search_suggestions",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "TikTok's search box order (most likely search first)",
          "page_max": 20,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "suggestion",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/search_top": {
      "get": {
        "description": "Returns the TikTok accounts, videos, hashtags and sounds a web search finds for your words, in one list, a page at a time. Each result carries its type and what the search index shows: an account's bio and followers, a video's caption and likes, a hashtag's post count, a sound's artist and video count. Add fill=true to also get each result's full live record in the same response.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/search_top/ (Markdown: https://socialtap.dev/docs/reference/tiktok/search_top/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/search_top/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/search_top/"
        },
        "operationId": "tiktok.search_top.list",
        "parameters": [
          {
            "description": "Words to search TikTok for, as a web search reads them: a topic, a name, a song (cooking, taylor swift, \"wine bar\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint.",
            "example": "cooking",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to search TikTok for, as a web search reads them: a topic, a name, a song (cooking, taylor swift, \"wine bar\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint.",
              "examples": [
                "cooking"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": {
                            "description": null,
                            "id": null,
                            "metrics": {
                              "post_count": null
                            },
                            "name": "cooking",
                            "thumbnail_url": null,
                            "url": "https://www.tiktok.com/tag/cooking"
                          },
                          "matched_url": "https://www.tiktok.com/tag/cooking",
                          "place": null,
                          "platform": "tiktok",
                          "platform_specific": {},
                          "position": 0,
                          "post": null,
                          "profile": null,
                          "snippet": "Everyone is cooking rice like this after seeing this genius idea #cooking #recipe #easyrecipe #quickrecipes #cook #chocolate #cake #dessert #viral #viraltiktok",
                          "sound": null,
                          "title": "cooking",
                          "type": "hashtag",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/tag/cooking"
                        },
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.tiktok.com/@cookinginthemidwest",
                          "place": null,
                          "platform": "tiktok",
                          "platform_specific": {},
                          "position": 1,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": null,
                            "display_name": "Luke Brown",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": null,
                              "following_count": null,
                              "post_count": null,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://www.tiktok.com/@cookinginthemidwest",
                            "username": "cookinginthemidwest"
                          },
                          "snippet": null,
                          "sound": null,
                          "title": "Luke Brown (@cookinginthemidwest)",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@cookinginthemidwest"
                        },
                        {
                          "approximate_fields": [
                            "post.published_at",
                            "post.text"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://www.tiktok.com/@cookinginthemidwest/video/7580894604610850078",
                          "place": null,
                          "platform": "tiktok",
                          "platform_specific": {},
                          "position": 2,
                          "post": {
                            "author": {
                              "avatar_url": null,
                              "display_name": "Cooking in the Midwest",
                              "id": null,
                              "is_verified": null,
                              "url": "https://www.tiktok.com/@cookinginthemidwest",
                              "username": "cookinginthemidwest"
                            },
                            "id": null,
                            "metrics": {
                              "comment_count": null,
                              "like_count": null,
                              "quote_count": null,
                              "repost_count": null,
                              "save_count": null,
                              "share_count": null,
                              "view_count": null
                            },
                            "published_at": "2025-12-06T23:42:50Z",
                            "text": "Our go to when we don’t feel like cooking or know what to make for dinner! INGREDIENTS Hoagie Rolls Ham Salami Pepperoni Provolone 1/2 cup of mayo 2 tbsp of red wine vinegar 1/2 tsp of salt and pepper 1 tsp of dried oregano, Italian seasoning, and garlic powder 1/2 tsp of red pep…",
                            "thumbnail_url": null,
                            "title": null,
                            "url": "https://www.tiktok.com/@cookinginthemidwest/video/7580894604610850078"
                          },
                          "profile": null,
                          "snippet": "TikTok video from Cooking in the Midwest (@cookinginthemidwest)",
                          "sound": null,
                          "title": "Our go to when we don’t feel like cooking or know what to make for dinner! INGREDIENTS Hoagie Rolls Ham Salami Pepperoni Provolone 1/2 cup of mayo 2 tbsp of red wine vinegar 1/2 tsp of salt and pepper 1 tsp of dried oregano, Italian seasoning, and garlic powder 1/2 tsp of red pep…",
                          "type": "post",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@cookinginthemidwest/video/7580894604610850078"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1331,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokSearch_topResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Accounts, videos, hashtags and sounds in one search",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.search_top",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/sound": {
      "get": {
        "description": "Returns a TikTok sound, a catalog track or a creator's original audio, from its link or ID, with its title, artists and how many posts use it. You also get the artists' TikTok accounts, clip length, cover art, an audio file link, album, the track's Spotify and Apple Music pages, and for an original sound the song TikTok matched its audio to.\n\nReturns `{data, meta}`: `data` is a `Sound` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/sound/ (Markdown: https://socialtap.dev/docs/reference/tiktok/sound/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/sound/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/sound/"
        },
        "operationId": "tiktok.sound.get",
        "parameters": [
          {
            "description": "A TikTok sound link (the sound page's tiktok.com/music/Different-Acoustic-6717159721276540930, or a share page's tiktok.com/share/music/6717159721276540930) or the sound's numeric ID (the clip ID at the end of that link, the music.id of a post). Short share links (vm.tiktok.com/…) are not accepted: open one and send the link it lands on.",
            "example": "https://www.tiktok.com/music/Different-Acoustic-6717159721276540930",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "A TikTok sound link (the sound page's tiktok.com/music/Different-Acoustic-6717159721276540930, or a share page's tiktok.com/share/music/6717159721276540930) or the sound's numeric ID (the clip ID at the end of that link, the music.id of a post). Short share links (vm.tiktok.com/…) are not accepted: open one and send the link it lands on.",
              "examples": [
                "https://www.tiktok.com/music/Different-Acoustic-6717159721276540930"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author_name": "Micah Tyler",
                        "authors": [
                          {
                            "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/0c546a533704730017922fba148f4cc9~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=11ca7945&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Micah Tyler",
                            "id": "7086245766293226538",
                            "is_verified": null,
                            "url": "https://www.tiktok.com/@micahtylertok",
                            "username": "micahtylertok"
                          }
                        ],
                        "cover_url": "https://p16-common.tiktokcdn-us.com/tos-alisg-v-2774/okeuMAAZnBBv88JZBjFEgjDOtWCZQ4AEEwfoQb~tplv-tiktokx-cropcenter:720:720.jpeg?dr=9584&t=4d5b0474&ps=933b5bde&shp=08d74b56&shcp=81f88b70&idc=useast5",
                        "duration_ms": 60000,
                        "id": "6717159721276540930",
                        "is_original": false,
                        "metrics": {
                          "post_count": 523
                        },
                        "platform": "tiktok",
                        "platform_specific": {
                          "tiktok": {
                            "album": "Different",
                            "is_commercial_music": false,
                            "matched_song": {
                              "id": "6717159725093390337",
                              "streaming_links": [
                                {
                                  "service": "apple_music",
                                  "url": "https://music.apple.com/song/1545544887"
                                },
                                {
                                  "service": "spotify",
                                  "url": "https://open.spotify.com/track/0hxxRQOLZLdbGDl4dgrsPV"
                                }
                              ]
                            }
                          }
                        },
                        "play_url": "https://sf19.tiktokcdn-us.com/obj/tos-alisg-ve-2774/oIBIZNfxOX2Nzi1WRH4ABroDirMAuIjwsGVov9",
                        "streaming_links": [
                          {
                            "service": "apple_music",
                            "url": "https://music.apple.com/song/1545544887"
                          },
                          {
                            "service": "spotify",
                            "url": "https://open.spotify.com/track/0hxxRQOLZLdbGDl4dgrsPV"
                          }
                        ],
                        "title": "Different (Acoustic)",
                        "unknown_fields": [],
                        "url": "https://www.tiktok.com/music/-6717159721276540930"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 257,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "sound",
                          "id": "6717159721276540930",
                          "url": "https://www.tiktok.com/music/-6717159721276540930"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokSoundResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Sound or song with its artists and post count",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.sound",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "sound",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/sound_posts": {
      "get": {
        "description": "Returns the public TikTok videos and photo posts that use a sound, from the sound's link or ID, a page at a time in TikTok's own order. Each has its caption, hashtags, mentions, publish time, duration, cover, photos, author and engagement counts.\n\nReturns `{data, page, meta}`: `data` holds up to 30 `Post` items (the shared schema, the same on every platform), TikTok's ranking of the sound's posts (the order its sound page shows). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/sound_posts/ (Markdown: https://socialtap.dev/docs/reference/tiktok/sound_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/sound_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/sound_posts/"
        },
        "operationId": "tiktok.sound_posts.list",
        "parameters": [
          {
            "description": "A TikTok sound link (the sound page's tiktok.com/music/Different-Acoustic-6717159721276540930, or a share page's tiktok.com/share/music/6717159721276540930) or the sound's numeric ID (the clip ID at the end of that link). Short share links (vm.tiktok.com/…) are not accepted: open one and send the link it lands on.",
            "example": "https://www.tiktok.com/music/Different-Acoustic-6717159721276540930",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "A TikTok sound link (the sound page's tiktok.com/music/Different-Acoustic-6717159721276540930, or a share page's tiktok.com/share/music/6717159721276540930) or the sound's numeric ID (the clip ID at the end of that link). Short share links (vm.tiktok.com/…) are not accepted: open one and send the link it lands on.",
              "examples": [
                "https://www.tiktok.com/music/Different-Acoustic-6717159721276540930"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 30,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 30,
              "maximum": 30,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count"
                          ],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast2a-avt-0068-euttp/021b48c3e3f6d8f2a6e82f72785f39f3~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=689e8ed0&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "M I C H E L L E 🌻",
                            "id": "6773210217221686278",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@m_i_c_h_e_l_l_e_89",
                            "username": "m_i_c_h_e_l_l_e_89"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [
                            "takecareofmaya",
                            "fyp",
                            "sosad"
                          ],
                          "id": "7247362041650924827",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 983,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast2a-i-photomode-euttp/013f34051fe444ee9fb26387cb5b99ab~tplv-photomode-image.jpeg?dr=9616&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=9b759fb9&idc=useast5&ftpl=1",
                              "width": 828
                            },
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 531,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast2a-i-photomode-euttp/84420d783a2e4c518ebe63b9e611925f~tplv-photomode-image.jpeg?dr=9616&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=9b759fb9&idc=useast5&ftpl=1",
                              "width": 828
                            },
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": 437,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast2a-i-photomode-euttp/0e6539c328194403b5aa11c2d9054f74~tplv-photomode-image.jpeg?dr=9616&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=9b759fb9&idc=useast5&ftpl=1",
                              "width": 828
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 2945,
                            "like_count": 24400,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 6175,
                            "share_count": 613,
                            "view_count": 1800000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAA79EVuIa2LrBo5qtnzSiPxq2SVNkKP7SWrGS8tEijuw7G3YlrnUdD7ckPTuYiDiWV",
                              "board": null,
                              "country_code": null,
                              "is_ad": false,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "Micah Tyler",
                                "cover_url": "https://p16-common.tiktokcdn-us.com/tos-alisg-v-2774/okeuMAAZnBBv88JZBjFEgjDOtWCZQ4AEEwfoQb~tplv-tiktokx-cropcenter:720:720.jpeg?dr=9584&t=4d5b0474&ps=933b5bde&shp=08d74b56&shcp=81f88b70&idc=useast5",
                                "duration_ms": 60000,
                                "id": "6717159721276540930",
                                "is_original": false,
                                "play_url": "https://sf19.tiktokcdn-us.com/obj/tos-alisg-ve-2774/oIBIZNfxOX2Nzi1WRH4ABroDirMAuIjwsGVov9",
                                "title": "Different (Acoustic)"
                              }
                            }
                          },
                          "platform_type": "photo",
                          "published_at": "2023-06-22T04:27:14Z",
                          "text": "#takecareofmaya #fyp #sosad #kowalskifamily #mustsee #netflix #foryoupage #emotional #justwow #icried #youwilltoo #toocruel #4u #netflixmustwatch #2023 #drsallysmith #rareillness #truestory #heartbreaking #cps #america #medicalnegligence there is no words for how fucked up there …",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast2a-i-photomode-euttp/013f34051fe444ee9fb26387cb5b99ab~tplv-photomode-image.jpeg?dr=9616&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=9b759fb9&idc=useast5&ftpl=1",
                          "title": null,
                          "type": "carousel",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@m_i_c_h_e_l_l_e_89/photo/7247362041650924827"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count"
                          ],
                          "author": {
                            "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/0c546a533704730017922fba148f4cc9~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=0ab84837&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Micah Tyler",
                            "id": "7086245766293226538",
                            "is_verified": true,
                            "url": "https://www.tiktok.com/@micahtylertok",
                            "username": "micahtylertok"
                          },
                          "coauthors": [],
                          "duration_ms": 41000,
                          "hashtags": [],
                          "id": "7701802307754773774",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 41000,
                              "expires_at": null,
                              "height": 1280,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/ooCgFVIwpOAiqiSTPGIX1cfilYB0BA2I1CI1ji~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 249,
                            "like_count": 11700,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 1381,
                            "share_count": 928,
                            "view_count": 91500
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAEdwuYUJfZcFMddE2j_F7VdBPJ-mFgfmhvS_OEZc_CwP9mgiFLDBlqsJOgEaAaHR5",
                              "board": null,
                              "country_code": null,
                              "is_ad": false,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "Micah Tyler",
                                "cover_url": "https://p16-common.tiktokcdn-us.com/tos-alisg-v-2774/okeuMAAZnBBv88JZBjFEgjDOtWCZQ4AEEwfoQb~tplv-tiktokx-cropcenter:720:720.jpeg?dr=9584&t=4d5b0474&ps=933b5bde&shp=08d74b56&shcp=81f88b70&idc=useast5",
                                "duration_ms": 60000,
                                "id": "6717159721276540930",
                                "is_original": false,
                                "play_url": "https://sf19.tiktokcdn-us.com/obj/tos-alisg-ve-2774/oIBIZNfxOX2Nzi1WRH4ABroDirMAuIjwsGVov9",
                                "title": "Different (Acoustic)"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-28T19:26:55Z",
                          "text": "Raise your hand if you ever just feel stuck in the same patterns day after day 🙋🏻‍♂️ If you came across this video, this is your sign to make a change!",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/ooCgFVIwpOAiqiSTPGIX1cfilYB0BA2I1CI1ji~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@micahtylertok/video/7701802307754773774"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count"
                          ],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-alisg-avt-0068/f36355f941e9077ec09362d4d1dfd543~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=b50a967e&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Thai",
                            "id": "6803307363471377414",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@eithailimafc",
                            "username": "eithailimafc"
                          },
                          "coauthors": [],
                          "duration_ms": 64000,
                          "hashtags": [
                            "tren",
                            "fo",
                            "fyp"
                          ],
                          "id": "7444557878633008440",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "pt",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 64000,
                              "expires_at": null,
                              "height": 722,
                              "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-maliva-p-0068/ogTUBeeVGCKOLV0I5gIwMIIfoCSQAqQg2ljZAA~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 576
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 73,
                            "like_count": 4019,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 118,
                            "share_count": 27,
                            "view_count": 88100
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAASieYwoFEQhdF-atwtqv764JDI3jCO07cy-EWm_XWBH6K01yQY1qTKdS9gOS2ER61",
                              "board": null,
                              "country_code": null,
                              "is_ad": false,
                              "is_ai_generated": false,
                              "location": {
                                "address": "Parana, Brazil",
                                "category": "Place and Address",
                                "city": null,
                                "id": "22535865224601460",
                                "name": "Londrina"
                              },
                              "music": {
                                "author_name": "Micah Tyler",
                                "cover_url": "https://p16-common.tiktokcdn-us.com/tos-alisg-v-2774/okeuMAAZnBBv88JZBjFEgjDOtWCZQ4AEEwfoQb~tplv-tiktokx-cropcenter:720:720.jpeg?dr=9584&t=4d5b0474&ps=933b5bde&shp=08d74b56&shcp=81f88b70&idc=useast5",
                                "duration_ms": 60000,
                                "id": "6717159721276540930",
                                "is_original": false,
                                "play_url": "https://sf19.tiktokcdn-us.com/obj/tos-alisg-ve-2774/oIBIZNfxOX2Nzi1WRH4ABroDirMAuIjwsGVov9",
                                "title": "Different (Acoustic)"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2024-12-04T14:06:49Z",
                          "text": "\"viver e realizar\"  #tren #fo #fyp #como #familia #realizacao #viver #independente",
                          "thumbnail_url": "https://p19-common-sign.tiktokcdn-us.com/tos-maliva-p-0068/ogTUBeeVGCKOLV0I5gIwMIIfoCSQAqQg2ljZAA~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@eithailimafc/video/7444557878633008440"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 649,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "sound",
                          "id": "6717159721276540930",
                          "url": "https://www.tiktok.com/music/-6717159721276540930"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokSound_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Videos and photo posts that use a sound",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.sound_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "TikTok's ranking of the sound's posts (the order its sound page shows)",
          "page_max": 30,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/top_ads": {
      "get": {
        "description": "Returns TikTok Creative Center's Top Ads board: the ads that performed best in a market over the last 7, 30 or 180 days. Each ad has its video, headline, brand, industry and campaign objective, with the board's rank, likes, click-through percentile and budget level. Narrow it by industry, objective or ad language, and rank it by Creative Center's own order or by impressions, likes, click-through, conversion or view-through rate. With no params you get the US board for the last 30 days.\n\nReturns `{data, page, meta}`: `data` holds up to 20 `Ad` items (the shared schema, the same on every platform), Creative Center's rank by rank_by, best first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/top_ads/ (Markdown: https://socialtap.dev/docs/reference/tiktok/top_ads/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/top_ads/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/top_ads/"
        },
        "operationId": "tiktok.top_ads.list",
        "parameters": [
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The market whose board to read, one of those Creative Center publishes: AR, AU, BR, CA, CO, FR, DE, ID, IT, JP, MY, MX, NL, PK, PH, RO, SA, SG, ZA, KR, ES, SE, TH, TR, AE, GB, US, VN.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "default": "US",
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The market whose board to read, one of those Creative Center publishes: AR, AU, BR, CA, CO, FR, DE, ID, IT, JP, MY, MX, NL, PK, PH, RO, SA, SG, ZA, KR, ES, SE, TH, TR, AE, GB, US, VN.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "The window the ranking counts over, in days back from the platform's latest update (each endpoint lists its own). Creative Center's windows: 7, 30 (default) or 180 days. Each window is its own board.",
            "example": "7",
            "in": "query",
            "name": "period",
            "schema": {
              "default": "30",
              "description": "The window the ranking counts over, in days back from the platform's latest update (each endpoint lists its own). Creative Center's windows: 7, 30 (default) or 180 days. Each window is its own board.",
              "enum": [
                "7",
                "30",
                "180"
              ],
              "examples": [
                "7"
              ],
              "type": "string"
            }
          },
          {
            "description": "How Creative Center ranks the board: for_you (its own blend, the default), or best first by impressions, likes, click-through rate (ctr), conversion rate (cvr), or the share of viewers who watched two or six seconds.",
            "example": "likes",
            "in": "query",
            "name": "rank_by",
            "schema": {
              "default": "for_you",
              "description": "How Creative Center ranks the board: for_you (its own blend, the default), or best first by impressions, likes, click-through rate (ctr), conversion rate (cvr), or the share of viewers who watched two or six seconds.",
              "enum": [
                "for_you",
                "impressions",
                "likes",
                "ctr",
                "cvr",
                "two_second_view_rate",
                "six_second_view_rate"
              ],
              "examples": [
                "likes"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only ads Creative Center files under this industry (or one of its sub-industries). Omit for every industry.",
            "example": "apps",
            "in": "query",
            "name": "industry",
            "schema": {
              "description": "Only ads Creative Center files under this industry (or one of its sub-industries). Omit for every industry.",
              "enum": [
                "education",
                "vehicle_and_transportation",
                "baby_kids_and_maternity",
                "beauty_and_personal_care",
                "tech_and_electronics",
                "travel",
                "household_products",
                "pets",
                "home_improvement",
                "apparel_and_accessories",
                "news_and_entertainment",
                "games",
                "food_and_beverage",
                "sports_and_outdoor",
                "health",
                "financial_services",
                "appliances",
                "apps",
                "business_services",
                "life_services",
                "e_commerce_non_app"
              ],
              "examples": [
                "apps"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only ads whose campaign optimized for this objective. Omit for every objective.",
            "example": "conversions",
            "in": "query",
            "name": "objective",
            "schema": {
              "description": "Only ads whose campaign optimized for this objective. Omit for every objective.",
              "enum": [
                "traffic",
                "app_installs",
                "conversions",
                "video_views",
                "reach",
                "lead_generation",
                "product_sales",
                "app_promotion"
              ],
              "examples": [
                "conversions"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only ads in this language (zh-Hant is Traditional Chinese). Omit for every language.",
            "example": "en",
            "in": "query",
            "name": "ad_language",
            "schema": {
              "description": "Only ads in this language (zh-Hant is Traditional Chinese). Omit for every language.",
              "enum": [
                "en",
                "es",
                "ar",
                "vi",
                "th",
                "de",
                "id",
                "pt",
                "fr",
                "ms",
                "nl",
                "ja",
                "it",
                "ro",
                "zh-Hant",
                "ko"
              ],
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 20,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "advertiser": {
                            "avatar_url": null,
                            "display_name": null,
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "approximate_fields": [],
                          "audience_size": null,
                          "country_codes": [
                            "US"
                          ],
                          "creatives": [
                            {
                              "body": null,
                              "cta_text": null,
                              "link_description": null,
                              "link_url": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": 20781,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": 720,
                                  "thumbnail_url": "https://p16-common-sign.tiktokcdn.com/tos-alisg-p-0051c001-sg/oUIHIbBqBgTQc9Ni3Es7fBJAe3dDvFrOsUhwGD~tplv-noop.image?dr=18692&refresh_token=64c44a34&x-expires=4070908800&x-signature=SCRUBBED&t=9276707c&ps=14f1eb3e&shp=9e36835a&shcp=317596d8&idc=my&VideoID=v14033g50000davc7dvog65l…",
                                  "type": "video",
                                  "url": "https://v16m-default.tiktokcdn.com/SCRUBBED/f2a52380/video/tos/alisg/tos-alisg-ve-0051c001-sg/oQQwvwCN2QbID92BEqngivDqFDfgAB6EFIf8cY/?a=0&bti=NTU4QDM1NGA%3D&&bt=874&ft=cApXJCz7ThWHd6C8LGZmo0P&mime_type=video_mp4&rc=aDpnaDs4aWQ3NDM5N2Q6NkBpajdnM285cmdmZDMzODYzNEAuMi0tMzRhXmAxXjAzX…",
                                  "width": 720
                                }
                              ],
                              "title": "Flooring Sale This Week Only!"
                            }
                          ],
                          "first_shown_at": null,
                          "id": "7691721167887056917",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": null,
                          "paid_by": null,
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "advertiser_business_id": null,
                              "advertiser_registry_location": null,
                              "budget": "low",
                              "category": "Interior Design & Decorating Services",
                              "ctr_top_percent": 63,
                              "is_removed": null,
                              "like_count": 7,
                              "objective": "Lead Generation",
                              "rank": 1,
                              "removal_country_codes": [],
                              "removal_reasons": [],
                              "targeting": null
                            }
                          },
                          "publisher_platforms": [
                            "tiktok"
                          ],
                          "reach": null,
                          "spend": null,
                          "type": "video",
                          "unknown_fields": [
                            "languages",
                            "platform_specific.tiktok.removal_country_codes",
                            "platform_specific.tiktok.removal_reasons"
                          ],
                          "url": "https://ads.tiktok.com/business/creativecenter/topads/7691721167887056917/pc/en"
                        },
                        {
                          "advertiser": {
                            "avatar_url": null,
                            "display_name": null,
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "approximate_fields": [],
                          "audience_size": null,
                          "country_codes": [
                            "US"
                          ],
                          "creatives": [
                            {
                              "body": null,
                              "cta_text": null,
                              "link_description": null,
                              "link_url": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": 25282,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": 1280,
                                  "thumbnail_url": "https://p16-common-sign.tiktokcdn.com/tos-alisg-p-0051c001-sg/oUhDPioYDsJVOA9BI3aizgYdEAzkFL5bjAvAM~tplv-noop.image?dr=18692&refresh_token=c8a4f8ed&x-expires=4070908800&x-signature=SCRUBBED&t=9276707c&ps=14f1eb3e&shp=9e36835a&shcp=317596d8&idc=my&VideoID=v14033g50000db1outnog65j5…",
                                  "type": "video",
                                  "url": "https://v16m-default.tiktokcdn.com/SCRUBBED/f2a52380/video/tos/alisg/tos-alisg-ve-0051c001-sg/ocgG0NLbIeoARfLAVnwAkGxeIvWbCbGhHgDhIi/?a=0&bti=NTU4QDM1NGA%3D&&bt=1088&ft=cApXJCz7ThWHd6C8LGZmo0P&mime_type=video_mp4&rc=NmY3PGlmOmk4ZjZkZzw6aEBpanc3bG05cndyZTMzODYzNEBgLjQxNDU0NTAxMF4y…",
                                  "width": 720
                                }
                              ],
                              "title": "9 Home Elements That Age Your Space Instantly"
                            }
                          ],
                          "first_shown_at": null,
                          "id": "7693148617658236936",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": null,
                          "paid_by": null,
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "advertiser_business_id": null,
                              "advertiser_registry_location": null,
                              "budget": "low",
                              "category": "Lifestyle News",
                              "ctr_top_percent": 50,
                              "is_removed": null,
                              "like_count": 5,
                              "objective": "Traffic",
                              "rank": 2,
                              "removal_country_codes": [],
                              "removal_reasons": [],
                              "targeting": null
                            }
                          },
                          "publisher_platforms": [
                            "tiktok"
                          ],
                          "reach": null,
                          "spend": null,
                          "type": "video",
                          "unknown_fields": [
                            "languages",
                            "platform_specific.tiktok.removal_country_codes",
                            "platform_specific.tiktok.removal_reasons"
                          ],
                          "url": "https://ads.tiktok.com/business/creativecenter/topads/7693148617658236936/pc/en"
                        },
                        {
                          "advertiser": {
                            "avatar_url": null,
                            "display_name": null,
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "approximate_fields": [],
                          "audience_size": null,
                          "country_codes": [
                            "US"
                          ],
                          "creatives": [
                            {
                              "body": null,
                              "cta_text": null,
                              "link_description": null,
                              "link_url": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": 27243,
                                  "expires_at": "2026-10-25T18:00:00Z",
                                  "height": 1280,
                                  "thumbnail_url": "https://p16-common-sign.tiktokcdn.com/tos-alisg-p-0051c001-sg/oEqAUk2MnB3I3AFNmBtQhsfDOuDUgBftuV6DE8~tplv-noop.image?dr=18692&refresh_token=331ddbb4&x-expires=4070908800&x-signature=SCRUBBED&t=9276707c&ps=14f1eb3e&shp=9e36835a&shcp=317596d8&idc=my&VideoID=v14033g50000datnapvog65j…",
                                  "type": "video",
                                  "url": "https://v16m-default.tiktokcdn.com/SCRUBBED/f2a52380/video/tos/alisg/tos-alisg-ve-0051c001-sg/o8PquQDWIBBEHK7hfDAgERAFHo6hieiTXWvNQh/?a=0&bti=NTU4QDM1NGA%3D&&bt=2105&ft=cApXJCz7ThWHd6C8LGZmo0P&mime_type=video_mp4&rc=aTlkNDY6ODkzNzlpaWVnZ0BpM3U8N205cnNxZDMzODYzNEA0NDVhYmJgNmIxXmNj…",
                                  "width": 720
                                }
                              ],
                              "title": "Залишайте заявку, щоб дізнатися більше"
                            }
                          ],
                          "first_shown_at": null,
                          "id": "7690605832515158037",
                          "impressions": null,
                          "is_active": null,
                          "is_political": null,
                          "languages": [],
                          "last_shown_at": null,
                          "paid_by": null,
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "advertiser_business_id": null,
                              "advertiser_registry_location": null,
                              "budget": "low",
                              "category": "Home Decor",
                              "ctr_top_percent": 88,
                              "is_removed": null,
                              "like_count": 6,
                              "objective": "Lead Generation",
                              "rank": 3,
                              "removal_country_codes": [],
                              "removal_reasons": [],
                              "targeting": null
                            }
                          },
                          "publisher_platforms": [
                            "tiktok"
                          ],
                          "reach": null,
                          "spend": null,
                          "type": "video",
                          "unknown_fields": [
                            "languages",
                            "platform_specific.tiktok.removal_country_codes",
                            "platform_specific.tiktok.removal_reasons"
                          ],
                          "url": "https://ads.tiktok.com/business/creativecenter/topads/7690605832515158037/pc/en"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 816,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokTop_adsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Best-performing ads by country, period and industry",
        "tags": [
          "TikTok Ad Library"
        ],
        "x-socialtap-endpoint": "tiktok.top_ads",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Creative Center's rank by rank_by, best first",
          "page_max": 20,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "ad",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/top_posts": {
      "get": {
        "description": "Returns TikTok Creative Center's top videos for a country over 7 or 30 days, ranked by views, organic views, engagement or six-second view rate. Each has its rank, caption, hashtags, cover, a playable video link, author with follower count, views in the window and lifetime and how many were organic, engagement rate and six-second view rate. With no parameters you get the US board for the latest 7 days, by views.\n\nReturns `{data, page, meta}`: `data` holds up to 20 `Post` items (the shared schema, the same on every platform), Creative Center's rank by the rank_by metric (1 = top). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/top_posts/ (Markdown: https://socialtap.dev/docs/reference/tiktok/top_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/top_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/top_posts/"
        },
        "operationId": "tiktok.top_posts.list",
        "parameters": [
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The market whose board to read, one of those Creative Center publishes: US, JP, VN, TH, ID.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "default": "US",
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The market whose board to read, one of those Creative Center publishes: US, JP, VN, TH, ID.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "The window the ranking counts over, in days back from the platform's latest update (each endpoint lists its own). Creative Center's windows: 7 (default) or 30 days. Each window is its own board.",
            "example": "7",
            "in": "query",
            "name": "period",
            "schema": {
              "default": "7",
              "description": "The window the ranking counts over, in days back from the platform's latest update (each endpoint lists its own). Creative Center's windows: 7 (default) or 30 days. Each window is its own board.",
              "enum": [
                "7",
                "30"
              ],
              "examples": [
                "7"
              ],
              "type": "string"
            }
          },
          {
            "description": "What the board ranks by in the window: views (the default; paid and organic), organic_views (views not bought as ads), engagement_rate (interactions per view) or six_second_view_rate (the share of views that lasted six seconds or more).",
            "example": "engagement_rate",
            "in": "query",
            "name": "rank_by",
            "schema": {
              "description": "What the board ranks by in the window: views (the default; paid and organic), organic_views (views not bought as ads), engagement_rate (interactions per view) or six_second_view_rate (the share of views that lasted six seconds or more).",
              "enum": [
                "views",
                "organic_views",
                "engagement_rate",
                "six_second_view_rate"
              ],
              "examples": [
                "engagement_rate"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only videos Creative Center files under this content category: its own board. Omit for the overall board.",
            "example": "fashion",
            "in": "query",
            "name": "category",
            "schema": {
              "description": "Only videos Creative Center files under this content category: its own board. Omit for the overall board.",
              "enum": [
                "beauty_and_care",
                "fashion",
                "food_and_beverage",
                "lifestyle_and_leisure",
                "technology_and_finance"
              ],
              "examples": [
                "fashion"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 20,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/7d6ee80f6e94a044a88786eec4ef128f~tplv-tiktokx-cropcenter:300:300.jpeg?dr=9638&refresh_token=9cb420e5&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=429d27ce&idc=useast5",
                            "display_name": "Meg Ann Co.",
                            "id": "6880574638150697990",
                            "is_verified": null,
                            "url": "https://www.tiktok.com/@megannco",
                            "username": "megannco"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [
                            "ad",
                            "shopifypartner"
                          ],
                          "id": "7678479724896587038",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": true,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": null,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/ocK3E0iPwBkRoAA5XXAPvCEAiBoiaIcqlA9Cp~tplv-tiktokx-origin.image?dr=9643&nonce=98074&refresh_token=524f684d00c1e5e8de7e7fa338f0765c&x-expires=4070908800&x-signature=SCRUBBED&idc=useast5&ps=13740610&shcp=89439a58&shp=c…",
                              "type": "video",
                              "url": "https://v16m-default.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast8/tos-useast8-pve-0068-tx2/o86niOqRAgxIAIiN1HEau2iLCbiPq7fcAVQ2B4/?a=2043&bti=NjQ7OGYwLzA6&&bt=1479&ft=GS-jnInz7ThiWdyGXq8Zmo&mime_type=video_mp4&rc=ODc4Mzk5M2g8aTY1OzpoNEBpM288ZWs5cndxZDMzaTczNEBfMmMuMWE0NjE…",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 60982257
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": 252785,
                              "author_sec_uid": null,
                              "board": {
                                "engagement_rate": 0.002308245167114756,
                                "organic_view_count": 6815757,
                                "period_end_at": "2026-10-31T00:00:00Z",
                                "period_engagement_rate": 0.0016317098947514215,
                                "period_organic_view_count": 4827523,
                                "period_six_second_view_rate": 0.03203383844307908,
                                "period_view_count": 38901523,
                                "rank": 1,
                                "six_second_view_rate": 0.03900531365810675
                              },
                              "country_code": null,
                              "is_ad": true,
                              "is_ai_generated": null,
                              "location": null,
                              "music": null
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-08-26T23:03:07Z",
                          "text": "Five years ago, I started my small business with no idea what it would grow into. From working out of my parents’ spare room to now having my own commercial space, @Shopify has been there every step of the way! Having the freedom to build a storefront that actually feels like my …",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/ocK3E0iPwBkRoAA5XXAPvCEAiBoiaIcqlA9Cp~tplv-tiktokx-origin.image?dr=9643&nonce=98074&refresh_token=524f684d00c1e5e8de7e7fa338f0765c&x-expires=4070908800&x-signature=SCRUBBED&idc=useast5&ps=13740610&shcp=89439a58&shp=c…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "mentions"
                          ],
                          "url": "https://www.tiktok.com/@megannco/video/7678479724896587038"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/bd593306c9ed3c915a4835f18e0b8cd0~tplv-tiktokx-cropcenter:300:300.jpeg?dr=9638&refresh_token=a99bc633&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=429d27ce&idc=useast5",
                            "display_name": "Fefe",
                            "id": "6532037588893564929",
                            "is_verified": null,
                            "url": "https://www.tiktok.com/@fefe",
                            "username": "fefe"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [
                            "Ruffles",
                            "DêPlayNaSuaOnda"
                          ],
                          "id": "7701364596807912734",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": true,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": null,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/oUEGAfEweXOAGIXAQVQMYM84gAoJAzavIqCLfj~tplv-tiktokx-origin.image?dr=9643&nonce=43595&refresh_token=47f05003f2004fe32f1c3c52afcd4ccd&x-expires=4070908800&x-signature=SCRUBBED&idc=useast5&ps=13740610&shcp=89439a58&shp=…",
                              "type": "video",
                              "url": "https://v16m-default.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast8/tos-useast8-ve-0068c001-tx2/o0XRDEADQZqgjsEbIBBUBVFDk4yIfEfL40A55W/?a=2043&bti=NjQ7OGYwLzA6&&bt=343&ft=GS-jnInz7ThiWdyGXq8Zmo&mime_type=video_mp4&rc=aTk0OWk6NDNpNTRmZDkzNkBpajM6ZnY5cm9lZTMzaTczNEAyYjVeMjAyX…",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 36746955
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": 17082503,
                              "author_sec_uid": null,
                              "board": {
                                "engagement_rate": 0.0018365603354073827,
                                "organic_view_count": 202204,
                                "period_end_at": "2026-10-31T00:00:00Z",
                                "period_engagement_rate": 0.0018365603354073827,
                                "period_organic_view_count": 202204,
                                "period_six_second_view_rate": 0.05010065159666401,
                                "period_view_count": 36746955,
                                "rank": 2,
                                "six_second_view_rate": 0.05010065159666401
                              },
                              "country_code": null,
                              "is_ad": true,
                              "is_ai_generated": null,
                              "location": null,
                              "music": null
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-27T15:08:23Z",
                          "text": "Medo? Só se for de acabar RUFFLES®️ @br_ruffles   #Ruffles #DêPlayNaSuaOnda",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/oUEGAfEweXOAGIXAQVQMYM84gAoJAzavIqCLfj~tplv-tiktokx-origin.image?dr=9643&nonce=43595&refresh_token=47f05003f2004fe32f1c3c52afcd4ccd&x-expires=4070908800&x-signature=SCRUBBED&idc=useast5&ps=13740610&shcp=89439a58&shp=…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "mentions"
                          ],
                          "url": "https://www.tiktok.com/@fefe/video/7701364596807912734"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/bd593306c9ed3c915a4835f18e0b8cd0~tplv-tiktokx-cropcenter:300:300.jpeg?dr=9638&refresh_token=a99bc633&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=429d27ce&idc=useast5",
                            "display_name": "Fefe",
                            "id": "6532037588893564929",
                            "is_verified": null,
                            "url": "https://www.tiktok.com/@fefe",
                            "username": "fefe"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [
                            "publicidade",
                            "Ruffles",
                            "DêPlayNaSuaOnda"
                          ],
                          "id": "7684011124739656991",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": true,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": "2026-10-25T18:00:00Z",
                              "height": null,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/ogejjeAR8AEFQ7CvAMjVT3EDFQIqWIAHeiAIxD~tplv-tiktokx-origin.image?dr=9643&nonce=17399&refresh_token=bb7d5053292654876361c80a65173799&x-expires=4070908800&x-signature=SCRUBBED&idc=useast5&ps=13740610&shcp=89439a58&shp=…",
                              "type": "video",
                              "url": "https://v16m-default.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast8/tos-useast8-pve-0068-tx2/okEeIsIAVLAFKExFimRK8ofO9dDrEBBEHQ4qjj/?a=2043&bti=NjQ7OGYwLzA6&&bt=408&ft=GS-jnInz7ThiWdyGXq8Zmo&mime_type=video_mp4&rc=OGQ0NWVnNzg7aTNmZTlnM0BpM2Ryc3g5cnVrZDMzaTczNEBhMi4xYF4wNmMx…",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 70021489
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": 17082503,
                              "author_sec_uid": null,
                              "board": {
                                "engagement_rate": 0.0013541271594495797,
                                "organic_view_count": 3816798,
                                "period_end_at": "2026-10-31T00:00:00Z",
                                "period_engagement_rate": 0.0012484027579240744,
                                "period_organic_view_count": 1170836,
                                "period_six_second_view_rate": 0.024768645613821798,
                                "period_view_count": 35180954,
                                "rank": 3,
                                "six_second_view_rate": 0.024519193030438022
                              },
                              "country_code": null,
                              "is_ad": true,
                              "is_ai_generated": null,
                              "location": null,
                              "music": null
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-09-10T20:47:47Z",
                          "text": "Existe combinação mais perfeita do que RUFFLES®️ e um bom filme? Impossível! Todo filme pede aquela crocância única para entrar no clima. 🎬✨ @br_ruffles  #publicidade #Ruffles #DêPlayNaSuaOnda",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/ogejjeAR8AEFQ7CvAMjVT3EDFQIqWIAHeiAIxD~tplv-tiktokx-origin.image?dr=9643&nonce=17399&refresh_token=bb7d5053292654876361c80a65173799&x-expires=4070908800&x-signature=SCRUBBED&idc=useast5&ps=13740610&shcp=89439a58&shp=…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [
                            "mentions"
                          ],
                          "url": "https://www.tiktok.com/@fefe/video/7684011124739656991"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1096,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokTop_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Ranked by country, period and metric",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.top_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Creative Center's rank by the rank_by metric (1 = top)",
          "page_max": 20,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/transcript": {
      "get": {
        "description": "Returns the timed transcript of a public TikTok video from its link or ID, read from its captions or, when it has none, its audio. You get the creator's edited captions, TikTok's auto-captions, or TikTok's own translation when lang asks for another language. Each segment has its start and end time, and text holds the whole transcript.\n\nReturns `{data, meta}`: `data` is a `Transcript` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit (captions) or 2 credits + 2 per started minute of media (speech-to-text) per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/transcript/ (Markdown: https://socialtap.dev/docs/reference/tiktok/transcript/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/transcript/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/transcript/"
        },
        "operationId": "tiktok.transcript.get",
        "parameters": [
          {
            "description": "TikTok video URL (tiktok.com/@user/video/<id>, m.tiktok.com/v/<id>.html, vm.tiktok.com/<code>, vt.tiktok.com/<code>, tiktok.com/t/<code>, embed URLs) or a numeric video ID.",
            "example": "7673108027645414678",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "TikTok video URL (tiktok.com/@user/video/<id>, m.tiktok.com/v/<id>.html, vm.tiktok.com/<code>, vt.tiktok.com/<code>, tiktok.com/t/<code>, embed URLs) or a numeric video ID.",
              "examples": [
                "https://www.tiktok.com/@scout2015/video/6718335390845095173"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). Selects the caption track (TikTok also offers its own translations); falls back to the video's original language, then any track. TikTok's three-letter codes (eng-US) work too.",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). Selects the caption track (TikTok also offers its own translations); falls back to the video's original language, then any track. TikTok's three-letter codes (eng-US) work too.",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "available_languages": [
                          "en"
                        ],
                        "duration_ms": 495000,
                        "id": "7673108027645414678",
                        "is_auto_generated": false,
                        "language": "en",
                        "platform": "tiktok",
                        "platform_specific": {},
                        "segments": [
                          {
                            "end_ms": 4820,
                            "start_ms": 100,
                            "text": "Let me show you how to make a Japanese cream stew!"
                          },
                          {
                            "end_ms": 8380,
                            "start_ms": 4821,
                            "text": "I think there is a way to definitely make it from scratch,"
                          },
                          {
                            "end_ms": 13120,
                            "start_ms": 8381,
                            "text": "but most Japanese people buy the stock for the cream stew."
                          }
                        ],
                        "source": "captions",
                        "text": "Let me show you how to make a Japanese cream stew! I think there is a way to definitely make it from scratch, but most Japanese people buy the stock for the cream stew. If you go to a Japanese supermarket, you can find this next to or near where the curry stock cubes are. This is…",
                        "url": "https://www.tiktok.com/@niinoclock/video/7673108027645414678"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "captions",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 507,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "7673108027645414678",
                          "url": "https://www.tiktok.com/@niinoclock/video/7673108027645414678"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokTranscriptResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "no_transcript": {
                    "$ref": "#/components/examples/no_transcript"
                  },
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.\n\n`no_transcript`: The video or audio exists but has no transcript: no caption track and no speech to transcribe. Do not retry. If the platform offers other languages, try one with lang.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Timed transcript from captions or the audio",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.transcript",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 122,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "captions"
            },
            {
              "credits": 2,
              "label": "2 credits + 2 per started minute of media",
              "max": 122,
              "per": 2,
              "source": "asr",
              "unit": "media_minute",
              "unit_max": 60
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "transcript",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/trending_hashtags": {
      "get": {
        "description": "Returns TikTok Creative Center's top trending hashtags for a country over 7, 30 or 90 days, overall or in one industry. Each has its rank, ID and tag page link, how many posts used it and how many views they drew in the window, its day-by-day popularity curve and its industry. With no parameters you get the US overall board for the latest 7 days.\n\nReturns `{data, page, meta}`: `data` holds up to 20 `Hashtag` items (the shared schema, the same on every platform), Creative Center's trend rank (1 = most popular). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/trending_hashtags/ (Markdown: https://socialtap.dev/docs/reference/tiktok/trending_hashtags/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/trending_hashtags/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/trending_hashtags/"
        },
        "operationId": "tiktok.trending_hashtags.list",
        "parameters": [
          {
            "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The market whose board to read, one of those Creative Center publishes: US, FR, DE, IT, ES, GB, AR, AU, BR, CA, CO, EG, ID, IL, JP, KR, MY, MX, PH, SA, SG, ZA, TW, TH, TR, AE, VN.",
            "example": "US",
            "in": "query",
            "name": "country",
            "schema": {
              "default": "US",
              "description": "Region: an ISO 3166-1 alpha-2 country code such as US or BR (case-insensitive). The market whose board to read, one of those Creative Center publishes: US, FR, DE, IT, ES, GB, AR, AU, BR, CA, CO, EG, ID, IL, JP, KR, MY, MX, PH, SA, SG, ZA, TW, TH, TR, AE, VN.",
              "examples": [
                "US"
              ],
              "type": "string"
            }
          },
          {
            "description": "The window the ranking counts over, in days back from the platform's latest update (each endpoint lists its own). Creative Center's windows: 7 (default), 30 or 90 days. Each window is its own board.",
            "example": "7",
            "in": "query",
            "name": "period",
            "schema": {
              "default": "7",
              "description": "The window the ranking counts over, in days back from the platform's latest update (each endpoint lists its own). Creative Center's windows: 7 (default), 30 or 90 days. Each window is its own board.",
              "enum": [
                "7",
                "30",
                "90"
              ],
              "examples": [
                "7"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only hashtags Creative Center files under this industry: its own board. Omit for the overall board.",
            "example": "games",
            "in": "query",
            "name": "industry",
            "schema": {
              "description": "Only hashtags Creative Center files under this industry: its own board. Omit for the overall board.",
              "enum": [
                "education",
                "vehicle_and_transportation",
                "baby_kids_and_maternity",
                "beauty_and_personal_care",
                "tech_and_electronics",
                "travel",
                "household_products",
                "pets",
                "home_improvement",
                "apparel_and_accessories",
                "news_and_entertainment",
                "games",
                "food_and_beverage",
                "sports_and_outdoor",
                "health"
              ],
              "examples": [
                "games"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 20,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "description": null,
                          "id": "7691443554018656263",
                          "metrics": {
                            "post_count": null
                          },
                          "name": "tiktokscaryhorrorcontest",
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "banner_url": null,
                              "industry": null,
                              "is_new_to_board": null,
                              "is_promoted": null,
                              "period_post_count": 73462,
                              "period_view_count": 312182870,
                              "rank": 1,
                              "rank_change": null,
                              "trend": [
                                {
                                  "popularity": 0,
                                  "start_at": "2026-10-09T00:00:00Z"
                                },
                                {
                                  "popularity": 0.49960472751387236,
                                  "start_at": "2026-10-10T00:00:00Z"
                                },
                                {
                                  "popularity": 0.6260068613247346,
                                  "start_at": "2026-10-11T00:00:00Z"
                                }
                              ],
                              "view_count": null
                            }
                          },
                          "thumbnail_url": null,
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/tag/tiktokscaryhorrorcontest"
                        },
                        {
                          "approximate_fields": [],
                          "description": null,
                          "id": "7462773581512966150",
                          "metrics": {
                            "post_count": null
                          },
                          "name": "marvelrivalsavengers",
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "banner_url": null,
                              "industry": "Games",
                              "is_new_to_board": null,
                              "is_promoted": null,
                              "period_post_count": 110088,
                              "period_view_count": 24120743,
                              "rank": 2,
                              "rank_change": null,
                              "trend": [
                                {
                                  "popularity": 0.9554338258860562,
                                  "start_at": "2026-10-09T00:00:00Z"
                                },
                                {
                                  "popularity": 1,
                                  "start_at": "2026-10-10T00:00:00Z"
                                },
                                {
                                  "popularity": 0.09724921698774618,
                                  "start_at": "2026-10-11T00:00:00Z"
                                }
                              ],
                              "view_count": null
                            }
                          },
                          "thumbnail_url": null,
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/tag/marvelrivalsavengers"
                        },
                        {
                          "approximate_fields": [],
                          "description": null,
                          "id": "7534678037321744414",
                          "metrics": {
                            "post_count": null
                          },
                          "name": "livecanbeeasy",
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "banner_url": null,
                              "industry": "News & Entertainment",
                              "is_new_to_board": null,
                              "is_promoted": null,
                              "period_post_count": 21285,
                              "period_view_count": 30155625,
                              "rank": 3,
                              "rank_change": null,
                              "trend": [
                                {
                                  "popularity": 0,
                                  "start_at": "2026-10-09T00:00:00Z"
                                },
                                {
                                  "popularity": 0.04117372687378199,
                                  "start_at": "2026-10-10T00:00:00Z"
                                },
                                {
                                  "popularity": 0.03219741952858018,
                                  "start_at": "2026-10-11T00:00:00Z"
                                }
                              ],
                              "view_count": null
                            }
                          },
                          "thumbnail_url": null,
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/tag/livecanbeeasy"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 706,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokTrending_hashtagsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Ranked by country, period and industry",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.trending_hashtags",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Creative Center's trend rank (1 = most popular)",
          "page_max": 20,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "hashtag",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktok/trending_posts": {
      "get": {
        "description": "Returns the videos and photo posts TikTok's explore page shows a logged-out US visitor, on its All tab or a topic tab. Each has its caption, author, sound and engagement counts, and each page is a new batch.\n\nReturns `{data, page, meta}`: `data` holds up to 30 `Post` items (the shared schema, the same on every platform), TikTok's explore feed order. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktok/trending_posts/ (Markdown: https://socialtap.dev/docs/reference/tiktok/trending_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktok/trending_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktok/trending_posts/"
        },
        "operationId": "tiktok.trending_posts.list",
        "parameters": [
          {
            "description": "Only posts of this explore tab. Omit for the All tab.",
            "example": "comedy",
            "in": "query",
            "name": "category",
            "schema": {
              "description": "Only posts of this explore tab. Omit for the All tab.",
              "enum": [
                "singing_and_dancing",
                "comedy",
                "sports",
                "anime_and_comics",
                "relationship",
                "shows",
                "lipsync",
                "daily_life",
                "beauty_care",
                "games",
                "society",
                "outfit",
                "cars",
                "food",
                "animals",
                "family",
                "drama",
                "fitness_and_health",
                "education",
                "technology"
              ],
              "examples": [
                "comedy"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 30,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 30,
              "maximum": 30,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count",
                            "metrics.share_count"
                          ],
                          "author": {
                            "avatar_url": "https://p19-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/c85a2637c437fd802b566ce7d86e7ffd~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=11ebccb3&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Peter Griffin",
                            "id": "7696276788455982094",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@theycallmepeety",
                            "username": "theycallmepeety"
                          },
                          "coauthors": [],
                          "duration_ms": 10000,
                          "hashtags": [
                            "petergriffin"
                          ],
                          "id": "7696297246949723423",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 10000,
                              "expires_at": null,
                              "height": 1280,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/oARGaA4gsA6ZsfBR2AVja6Bf1dBNt9EfYfeejh~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 9878,
                            "like_count": 1400000,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 98303,
                            "share_count": 585700,
                            "view_count": 15200000
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAUN-8ze7D5d2lvqUgYTSDjewkf_sMsP5vzZwhYOsqWFFnDXAkTFjWciq69Q0_StBt",
                              "board": null,
                              "country_code": null,
                              "is_ad": false,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "Patrick Sébastien",
                                "cover_url": "https://p19-common.tiktokcdn-us.com/tos-alisg-v-2774/2333d276a89248acaaf9a2ce54682136~tplv-tiktokx-cropcenter:720:720.jpeg?dr=9584&t=4d5b0474&ps=933b5bde&shp=08d74b56&shcp=81f88b70&idc=useast5",
                                "duration_ms": 30000,
                                "id": "105605900",
                                "is_original": false,
                                "play_url": "https://sf16.tiktokcdn-us.com/obj/tos-alisg-ve-2774/fdde51d720b044c39cfc9216be9ee39c",
                                "title": "Toc toc"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-13T23:24:10Z",
                          "text": "I do my lil dancy dance #petergriffin",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/oARGaA4gsA6ZsfBR2AVja6Bf1dBNt9EfYfeejh~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@theycallmepeety/video/7696297246949723423"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count"
                          ],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/3564989e3441a77ec7b995c1d439567f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=96360d8f&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Addi 5.k",
                            "id": "7385156308259161121",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@smileytadizz",
                            "username": "smileytadizz"
                          },
                          "coauthors": [],
                          "duration_ms": 22000,
                          "hashtags": [
                            "fyp",
                            "viralvideo",
                            "salish"
                          ],
                          "id": "7700252664638016800",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 22000,
                              "expires_at": null,
                              "height": 1024,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast2a-p-0037-euttp/o8AA2DfEXQ3wqFLmJICsRnA8AqEUFZEADeDMyc~tplv-tiktokx-dmt-logom:tos-useast2a-i-0068-euttp/oMMWmFD0REDTtIAEYcEExsCAyAiQwnAK3qfXfD.image?dr=9634&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f…",
                              "type": "video",
                              "url": null,
                              "width": 576
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 28,
                            "like_count": 15200,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 3851,
                            "share_count": 706,
                            "view_count": 482800
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAffcpuH0B4mDMMIgIaT9XBQXMTwkc5nag2HaBReZBMq2KF9F7VPmK6PJ3rQ8Bhhz3",
                              "board": null,
                              "country_code": null,
                              "is_ad": false,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "Addi 5.k",
                                "cover_url": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/3564989e3441a77ec7b995c1d439567f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=96360d8f&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 22000,
                                "id": "7700252697424890657",
                                "is_original": true,
                                "play_url": "https://v16m.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast2a/tos-useast2a-v-2370-euttp/o4AsImgKHDCglmAeAMF8DJqAGUjQ1BI3IhfJ5E/?a=1233&bti=ODszNWYuMDE6&&bt=125&ft=GSDrKInz7ThIyHAGXq8Zmo&mime_type=audio_mpeg&rc=M3Q2bng5cjRmZTMzZjU8NUBpM3Q2bng5cjRmZTMzZjU8NUBsMG4vMmRzamJhLS1kM…",
                                "title": "izvorni zvuk"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-24T15:13:10Z",
                          "text": "poor salish #fyp #viralvideo #salish #LA #california",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast2a-p-0037-euttp/o8AA2DfEXQ3wqFLmJICsRnA8AqEUFZEADeDMyc~tplv-tiktokx-dmt-logom:tos-useast2a-i-0068-euttp/oMMWmFD0REDTtIAEYcEExsCAyAiQwnAK3qfXfD.image?dr=9634&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f…",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@smileytadizz/video/7700252664638016800"
                        },
                        {
                          "approximate_fields": [
                            "metrics.view_count",
                            "metrics.like_count"
                          ],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/d35ba2b5b6dcba916e652ab6854a8d12~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=3dbf13d1&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                            "display_name": "Milk lard",
                            "id": "7006760049079878661",
                            "is_verified": false,
                            "url": "https://www.tiktok.com/@milklard",
                            "username": "milklard"
                          },
                          "coauthors": [],
                          "duration_ms": 25000,
                          "hashtags": [
                            "relatable",
                            "mexican",
                            "mexicanmemes"
                          ],
                          "id": "7697417641027259662",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 25000,
                              "expires_at": null,
                              "height": 1280,
                              "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/o8utS4sgao42KXkKAAmAgD5dEqh4iPBEBA1iI~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                              "type": "video",
                              "url": null,
                              "width": 720
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 291,
                            "like_count": 46100,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": 5370,
                            "share_count": 4337,
                            "view_count": 663200
                          },
                          "platform": "tiktok",
                          "platform_specific": {
                            "tiktok": {
                              "author_follower_count": null,
                              "author_sec_uid": "MS4wLjABAAAAs8cmTgFigZN2SkC39aSu65y1D34RWlZl6s4bIEXok2XJsv9sWucS2q5QF9kgO5v2",
                              "board": null,
                              "country_code": null,
                              "is_ad": false,
                              "is_ai_generated": false,
                              "location": null,
                              "music": {
                                "author_name": "ProMove",
                                "cover_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast2a-avt-0068-giso/f4d35d9e0dc8f4db995c09fe56028947~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=f687a211&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5",
                                "duration_ms": 168000,
                                "id": "7234899642008636187",
                                "is_original": true,
                                "play_url": "https://v16m.tiktokcdn-us.com/SCRUBBED/f2a52380/video/tos/useast2a/tos-useast2a-v-27dcd7-aiso/46d07c10ce864bb1ab8371517e3aa811/?a=1233&bti=ODszNWYuMDE6&&bt=125&ft=GSDrKInz7ThIyHAGXq8Zmo&mime_type=audio_mpeg&rc=amxocDY6ZnhyazMzZjU8M0BpamxocDY6ZnhyazMzZjU8M0Avcm5rcjRfYWdgLS1kMWNzYS…",
                                "title": "sunet original"
                              }
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2026-10-16T23:52:10Z",
                          "text": "You can move out of your Mexican household but you can’t stop being Mexican, tried so hard to store my pots and pans in a cute way but they belong in the oven… is it just a Mexican thing to use the oven as a storage space for pots n pans ?  - - #relatable #mexican #mexicanmemes #…",
                          "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/o8utS4sgao42KXkKAAmAgD5dEqh4iPBEBA1iI~tplv-tiktokx-origin.image?dr=9636&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=81f88b70&shcp=43f4a2f9&idc=useast5",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://www.tiktok.com/@milklard/video/7697417641027259662"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktok",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1019,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokTrending_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "What the explore page shows now, by topic",
        "tags": [
          "TikTok"
        ],
        "x-socialtap-endpoint": "tiktok.trending_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "TikTok's explore feed order",
          "page_max": 30,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktokshop/product": {
      "get": {
        "description": "Returns a public TikTok Shop product from its link or ID, with its price, discount, units sold and every variant's price and stock. It also has the description, rating with its star breakdown, specifications, category, images, shipping fee and delivery estimate, and the shop selling it with its rating, followers and units sold.\n\nReturns `{data, meta}`: `data` is a `Product` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktokshop/product/ (Markdown: https://socialtap.dev/docs/reference/tiktokshop/product/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktokshop/product/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktokshop/product/"
        },
        "operationId": "tiktokshop.product.get",
        "parameters": [
          {
            "description": "A TikTok Shop product link (shop.tiktok.com/us/pdp/<slug>/<id>, www.tiktok.com/shop/pdp/<id>, or the app's /view/product/<id> link) or the product ID. US products.",
            "example": "https://www.tiktok.com/shop/pdp/1729587769570529799",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "A TikTok Shop product link (shop.tiktok.com/us/pdp/<slug>/<id>, www.tiktok.com/shop/pdp/<id>, or the app's /view/product/<id> link) or the product ID. US products.",
              "examples": [
                "https://shop.tiktok.com/us/pdp/goli-ashwagandha-gummies-with-vitamin-d-ksm-66-vegan-non-gmo/1729587769570529799"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "platform_specific.tiktokshop.shop.rating"
                        ],
                        "attributes": [
                          {
                            "name": "Brand",
                            "value": "Goli"
                          },
                          {
                            "name": "Container type",
                            "value": "Bottle"
                          },
                          {
                            "name": "Flavor",
                            "value": "Berry"
                          }
                        ],
                        "availability": "in_stock",
                        "category": "Vitamins Supplements",
                        "category_id": "1298960",
                        "condition": null,
                        "condition_label": null,
                        "country_code": "US",
                        "currency": "USD",
                        "description": "Goli Nutrition has sold over 90 Million bottles of gummy vitamins.\n\nVegan, Non-GMO, Gluten-free & Gelatin-free: Each bottle of Goli contains 60 delicious, vegan, non-gmo, gluten-free & gelatin-free Apple Cider Vinegar gummies, which makes them suitable for almost any lifestyle. N…",
                        "id": "1729587769570529799",
                        "max_price": 58.47,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": null,
                            "expires_at": null,
                            "height": 800,
                            "thumbnail_url": null,
                            "type": "image",
                            "url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/b0d9acd7ae184c8d89e2e498941485b6~tplv-fhlh96nyum-crop-webp:800:800.webp?dr=12190&t=555f072d&ps=933b5bde&shp=c940a200&shcp=9b759fb9&idc=useast5&from=3376456192",
                            "width": 800
                          },
                          {
                            "alt_text": null,
                            "duration_ms": null,
                            "expires_at": null,
                            "height": 800,
                            "thumbnail_url": null,
                            "type": "image",
                            "url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/f14272ec92ff4d06996daf72fab0ae5b~tplv-fhlh96nyum-crop-webp:800:800.webp?dr=12190&t=555f072d&ps=933b5bde&shp=c940a200&shcp=9b759fb9&idc=useast5&from=3376456192",
                            "width": 800
                          },
                          {
                            "alt_text": null,
                            "duration_ms": null,
                            "expires_at": null,
                            "height": 800,
                            "thumbnail_url": null,
                            "type": "image",
                            "url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/35caa171a9874ecd987b7a23fa4ea0a0~tplv-fhlh96nyum-crop-webp:800:800.webp?dr=12190&t=555f072d&ps=933b5bde&shp=c940a200&shcp=9b759fb9&idc=useast5&from=3376456192",
                            "width": 800
                          }
                        ],
                        "original_price": 74.1,
                        "platform": "tiktokshop",
                        "platform_specific": {
                          "tiktokshop": {
                            "brand": "Goli",
                            "delivery_max_days": 6,
                            "delivery_min_days": 3,
                            "metrics": {
                              "rating_distribution": {
                                "five_star_count": 61276,
                                "four_star_count": 4662,
                                "one_star_count": 3255,
                                "three_star_count": 1804,
                                "two_star_count": 761
                              },
                              "review_count": 71758,
                              "sold_count": 866215,
                              "stock_count": 240898
                            },
                            "rating": 4.671493073942975,
                            "shop": {
                              "metrics": {
                                "follower_count": 601584,
                                "product_count": 53,
                                "review_count": 412852,
                                "sold_count": 5812862
                              },
                              "rating": 4.6
                            },
                            "variants": [
                              {
                                "availability": "in_stock",
                                "id": "1729587788239049223",
                                "image_url": null,
                                "options": [],
                                "original_price": 74.1,
                                "price": 58.47,
                                "stock_count": 240898,
                                "title": null
                              }
                            ]
                          }
                        },
                        "price": 58.47,
                        "seller": {
                          "avatar_url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/e7478d3e93d4487a9e772fa74e10f506~tplv-fhlh96nyum-resize-webp:300:300.webp?dr=12185&t=555f072d&ps=933b5bde&shp=905da467&shcp=607f11de&idc=useast5&from=2422056039",
                          "display_name": "Goli Nutrition",
                          "id": "7495794203056835079",
                          "is_verified": true,
                          "url": "https://shop.tiktok.com/us/store/goli-nutrition/7495794203056835079",
                          "username": null
                        },
                        "shipping": {
                          "fee": 0,
                          "is_offered": true
                        },
                        "thumbnail_url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/b0d9acd7ae184c8d89e2e498941485b6~tplv-fhlh96nyum-crop-webp:800:800.webp?dr=12190&t=555f072d&ps=933b5bde&shp=c940a200&shcp=9b759fb9&idc=useast5&from=3376456192",
                        "title": "3 Bottles of Goli Ashwagandha & Vitamin D Gummy - Mixed Berry, KSM-66, Vegan, Plant Based, Non-GMO, Gluten & Gelatin Free",
                        "type": "product",
                        "unknown_fields": [],
                        "url": "https://shop.tiktok.com/us/pdp/1729587769570529799"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktokshop",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1198,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "product",
                          "id": "1729587769570529799",
                          "url": "https://shop.tiktok.com/us/pdp/1729587769570529799"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokshopProductResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Price, variants, stock and units sold",
        "tags": [
          "TikTok Shop"
        ],
        "x-socialtap-endpoint": "tiktokshop.product",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "product",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktokshop/products": {
      "get": {
        "description": "Returns the products a public TikTok Shop store has on sale, best sellers first, from its storefront link or seller ID. Each has its title, price and price before discount, units sold, rating and review count, brand, main image and store, a page at a time.\n\nReturns `{data, page, meta}`: `data` holds up to 20 `Product` items (the shared schema, the same on every platform), TikTok Shop's store order: best-selling first (units sold, most first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktokshop/products/ (Markdown: https://socialtap.dev/docs/reference/tiktokshop/products/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktokshop/products/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktokshop/products/"
        },
        "operationId": "tiktokshop.products.list",
        "parameters": [
          {
            "description": "A TikTok Shop shop: its storefront link (shop.tiktok.com/us/store/<slug>/<seller id>, www.tiktok.com/shop/store/<slug>/<seller id>) or its seller ID. US shops.",
            "example": "https://shop.tiktok.com/us/store/goli-nutrition/7495794203056835079",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "A TikTok Shop shop: its storefront link (shop.tiktok.com/us/store/<slug>/<seller id>, www.tiktok.com/shop/store/<slug>/<seller id>) or its seller ID. US shops.",
              "examples": [
                "https://shop.tiktok.com/us/store/goli-nutrition/7495794203056835079"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 20,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "platform_specific.tiktokshop.rating"
                          ],
                          "attributes": [],
                          "availability": null,
                          "category": null,
                          "category_id": null,
                          "condition": null,
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "1729527313880355335",
                          "max_price": 19.47,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 1500,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p19-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/2bc69aa9f6084480beee1bb4a8db3a69~tplv-fhlh96nyum-crop-webp:1500:1500.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=a6e80448&idc=useast5&from=2378011839",
                              "width": 1500
                            }
                          ],
                          "original_price": 24.7,
                          "platform": "tiktokshop",
                          "platform_specific": {
                            "tiktokshop": {
                              "brand": "Goli",
                              "delivery_max_days": null,
                              "delivery_min_days": null,
                              "metrics": {
                                "rating_distribution": null,
                                "review_count": 94487,
                                "sold_count": 1306510,
                                "stock_count": null
                              },
                              "rating": 4.5,
                              "shop": null,
                              "variants": []
                            }
                          },
                          "price": 19.47,
                          "seller": {
                            "avatar_url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/e7478d3e93d4487a9e772fa74e10f506~tplv-fhlh96nyum-resize-png:300:300.png?dr=12184&t=555f072d&ps=933b5bde&shp=905da467&shcp=d9d491bf&idc=useast5&from=2422056039",
                            "display_name": "Goli Nutrition",
                            "id": "7495794203056835079",
                            "is_verified": true,
                            "url": "https://shop.tiktok.com/us/store/goli-nutrition/7495794203056835079",
                            "username": null
                          },
                          "shipping": {
                            "fee": 0,
                            "is_offered": true
                          },
                          "thumbnail_url": "https://p19-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/2bc69aa9f6084480beee1bb4a8db3a69~tplv-fhlh96nyum-crop-webp:1500:1500.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=a6e80448&idc=useast5&from=2378011839",
                          "title": "Goli Ashwagandha & Vitamin D Gummy - Mixed Berry, KSM-66, Vegan, Plant Based, Non-GMO, Gluten-Free & Gelatin Free. America's #1 Ashwagandha Brand",
                          "type": "product",
                          "unknown_fields": [
                            "attributes",
                            "platform_specific.tiktokshop.variants"
                          ],
                          "url": "https://shop.tiktok.com/us/pdp/1729527313880355335"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.tiktokshop.rating"
                          ],
                          "attributes": [],
                          "availability": null,
                          "category": null,
                          "category_id": null,
                          "condition": null,
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "1731194857673101831",
                          "max_price": 49.37,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 3000,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/02f1b939f53d400998099bfad0f85a14~tplv-fhlh96nyum-crop-webp:3000:3000.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=a6e80448&idc=useast5&from=2378011839",
                              "width": 3000
                            }
                          ],
                          "original_price": 74.1,
                          "platform": "tiktokshop",
                          "platform_specific": {
                            "tiktokshop": {
                              "brand": "Goli",
                              "delivery_max_days": null,
                              "delivery_min_days": null,
                              "metrics": {
                                "rating_distribution": null,
                                "review_count": 47921,
                                "sold_count": 1043069,
                                "stock_count": null
                              },
                              "rating": 4.5,
                              "shop": null,
                              "variants": []
                            }
                          },
                          "price": 49.37,
                          "seller": {
                            "avatar_url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/e7478d3e93d4487a9e772fa74e10f506~tplv-fhlh96nyum-resize-png:300:300.png?dr=12184&t=555f072d&ps=933b5bde&shp=905da467&shcp=d9d491bf&idc=useast5&from=2422056039",
                            "display_name": "Goli Nutrition",
                            "id": "7495794203056835079",
                            "is_verified": true,
                            "url": "https://shop.tiktok.com/us/store/goli-nutrition/7495794203056835079",
                            "username": null
                          },
                          "shipping": {
                            "fee": 0,
                            "is_offered": true
                          },
                          "thumbnail_url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/02f1b939f53d400998099bfad0f85a14~tplv-fhlh96nyum-crop-webp:3000:3000.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=a6e80448&idc=useast5&from=2378011839",
                          "title": "Goli Zero Sugar Best Seller Trio – Daily Gut & Wellness Support with Pre, Post & Probiotics, Apple Cider Vinegar, Ashwagandha & L-Theanine Gummies",
                          "type": "product",
                          "unknown_fields": [
                            "attributes",
                            "platform_specific.tiktokshop.variants"
                          ],
                          "url": "https://shop.tiktok.com/us/pdp/1731194857673101831"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.tiktokshop.rating"
                          ],
                          "attributes": [],
                          "availability": null,
                          "category": null,
                          "category_id": null,
                          "condition": null,
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "1729587769570529799",
                          "max_price": 58.47,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 1500,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p19-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/b0d9acd7ae184c8d89e2e498941485b6~tplv-fhlh96nyum-crop-webp:1500:1500.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=a6e80448&idc=useast5&from=2378011839",
                              "width": 1500
                            }
                          ],
                          "original_price": 74.1,
                          "platform": "tiktokshop",
                          "platform_specific": {
                            "tiktokshop": {
                              "brand": "Goli",
                              "delivery_max_days": null,
                              "delivery_min_days": null,
                              "metrics": {
                                "rating_distribution": null,
                                "review_count": 71758,
                                "sold_count": 866215,
                                "stock_count": null
                              },
                              "rating": 4.7,
                              "shop": null,
                              "variants": []
                            }
                          },
                          "price": 58.47,
                          "seller": {
                            "avatar_url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/e7478d3e93d4487a9e772fa74e10f506~tplv-fhlh96nyum-resize-png:300:300.png?dr=12184&t=555f072d&ps=933b5bde&shp=905da467&shcp=d9d491bf&idc=useast5&from=2422056039",
                            "display_name": "Goli Nutrition",
                            "id": "7495794203056835079",
                            "is_verified": true,
                            "url": "https://shop.tiktok.com/us/store/goli-nutrition/7495794203056835079",
                            "username": null
                          },
                          "shipping": {
                            "fee": 0,
                            "is_offered": true
                          },
                          "thumbnail_url": "https://p19-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/b0d9acd7ae184c8d89e2e498941485b6~tplv-fhlh96nyum-crop-webp:1500:1500.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=a6e80448&idc=useast5&from=2378011839",
                          "title": "3 Bottles of Goli Ashwagandha & Vitamin D Gummy - Mixed Berry, KSM-66, Vegan, Plant Based, Non-GMO, Gluten & Gelatin Free",
                          "type": "product",
                          "unknown_fields": [
                            "attributes",
                            "platform_specific.tiktokshop.variants"
                          ],
                          "url": "https://shop.tiktok.com/us/pdp/1729587769570529799"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktokshop",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 798,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "7495794203056835079",
                          "url": "https://shop.tiktok.com/us/store/goli-nutrition/7495794203056835079"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokshopProductsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Products a store sells, best sellers first",
        "tags": [
          "TikTok Shop"
        ],
        "x-socialtap-endpoint": "tiktokshop.products",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "TikTok Shop's store order: best-selling first (units sold, most first)",
          "page_max": 20,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "product",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktokshop/reviews": {
      "get": {
        "description": "Returns the reviews a public TikTok Shop product page shows, from the product's link or ID, with star ratings, text and photos. Each review has the variant bought, when and from which country it was posted, whether the purchase is verified or the review incentivized, and the reviewer as TikTok Shop shows them: a masked name, and their TikTok user ID and avatar unless the review is anonymous.\n\nReturns `{data, page, meta}`: `data` holds up to 5 `Review` items (the shared schema, the same on every platform), TikTok Shop's recommended order (the order its product page shows reviews in). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktokshop/reviews/ (Markdown: https://socialtap.dev/docs/reference/tiktokshop/reviews/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktokshop/reviews/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktokshop/reviews/"
        },
        "operationId": "tiktokshop.reviews.list",
        "parameters": [
          {
            "description": "A TikTok Shop product link (shop.tiktok.com/us/pdp/<slug>/<id>, www.tiktok.com/shop/pdp/<id>, or the app's /view/product/<id> link) or the product ID. US products.",
            "example": "https://shop.tiktok.com/us/pdp/root-labs-liposomal-magnesium-gummies-stress-relief-sleep/1729477768109462617",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "A TikTok Shop product link (shop.tiktok.com/us/pdp/<slug>/<id>, www.tiktok.com/shop/pdp/<id>, or the app's /view/product/<id> link) or the product ID. US products.",
              "examples": [
                "https://shop.tiktok.com/us/pdp/root-labs-liposomal-magnesium-gummies-stress-relief-sleep/1729477768109462617"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 5,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 5,
              "maximum": 5,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": null,
                            "display_name": "🌈**😂",
                            "id": null,
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "country_code": "US",
                          "id": "7643069466080282382",
                          "is_incentivized": false,
                          "is_verified_purchase": true,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/fec693639a5e4f23b2a073abe6aaafcd~tplv-fhlh96nyum-crop-webp:300:300.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=607f11de&idc=useast5&from=2378011839",
                              "width": null
                            },
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/caac5b714ac94c09b42b4447d29af5ad~tplv-fhlh96nyum-crop-webp:300:300.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=607f11de&idc=useast5&from=2378011839",
                              "width": null
                            },
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/d48509acfcff48e986d8a65d34b1bdaa~tplv-fhlh96nyum-crop-webp:300:300.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=607f11de&idc=useast5&from=2378011839",
                              "width": null
                            }
                          ],
                          "metrics": {
                            "helpful_count": null
                          },
                          "platform": "tiktokshop",
                          "platform_specific": {},
                          "product_id": "1729477768109462617",
                          "published_at": "2026-05-23T12:53:11Z",
                          "rating": 1,
                          "text": "Terrible experience cuz the nerve 2 charge my card and never deLiver package IS not OK❗️I will never order from these ppl and trynna get replacement,return and/or refund has been denied-6x🤬‼️🧐🧐Im sick & tired of sellers like this one & am obviously a very dissatisfied customer🛑Af…",
                          "title": null,
                          "unknown_fields": [],
                          "url": null,
                          "variant_id": "1732274509536399449",
                          "variant_title": "60s x 4"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/fcefca9f7b252860d895d397be45c2a2~tplv-tiktokx-cropcenter:100:100.jpg?dr=9640&refresh_token=e81fcc75&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=5f8d3399&idc=useast5",
                            "display_name": "M**s L**a L**a 🐲**🫶",
                            "id": "6813476641236632581",
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "country_code": "US",
                          "id": "7686563692952684301",
                          "is_incentivized": false,
                          "is_verified_purchase": true,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/7bf0bd8ba0984350823b7491ff499ade~tplv-fhlh96nyum-crop-webp:300:300.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=607f11de&idc=useast5&from=2378011839",
                              "width": null
                            },
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/8edda6e8ce3e48b4be07c0e1d8139529~tplv-fhlh96nyum-crop-webp:300:300.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=607f11de&idc=useast5&from=2378011839",
                              "width": null
                            },
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/e79176ec2ed94d0693dda8a1699c89a2~tplv-fhlh96nyum-crop-webp:300:300.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=607f11de&idc=useast5&from=2378011839",
                              "width": null
                            }
                          ],
                          "metrics": {
                            "helpful_count": null
                          },
                          "platform": "tiktokshop",
                          "platform_specific": {},
                          "product_id": "1729477768109462617",
                          "published_at": "2026-09-17T17:52:59Z",
                          "rating": 5,
                          "text": "My first purchase I did the two packs and I didn’t think I was going to like them, but I absolutely fell in love with you. Don’t eat more than two a day but they are sweet eat white candy. I have ADHD 52 years old. I’m never sleepy melatonin never work this melatonin actually abs…",
                          "title": null,
                          "unknown_fields": [],
                          "url": null,
                          "variant_id": "1732274543402061913",
                          "variant_title": "60s x 1"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/12c5eb38039e055d47d0b131bccf0d88~tplv-tiktokx-cropcenter:100:100.jpg?dr=9640&refresh_token=08b28932&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=5f8d3399&idc=useast5",
                            "display_name": "S**e B**e",
                            "id": "7480343496907211818",
                            "is_verified": null,
                            "url": null,
                            "username": null
                          },
                          "country_code": "US",
                          "id": "7640667122487297806",
                          "is_incentivized": false,
                          "is_verified_purchase": true,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": null,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/fe8c90c12f854650987caf0dbe6b48ff~tplv-fhlh96nyum-crop-webp:300:300.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=607f11de&idc=useast5&from=2378011839",
                              "width": null
                            }
                          ],
                          "metrics": {
                            "helpful_count": null
                          },
                          "platform": "tiktokshop",
                          "platform_specific": {},
                          "product_id": "1729477768109462617",
                          "published_at": "2026-05-17T01:31:10Z",
                          "rating": 5,
                          "text": "The product bag was bigger than I expected\nFlavor: Is really good I dont feel anyone would be disappointed with the flavor\nPerformance: Ill be starting tonight so we shall see. Ive used ashwaganda before, worked like a charm. So Im assure this will be a hit as well",
                          "title": null,
                          "unknown_fields": [],
                          "url": null,
                          "variant_id": "1732274543402061913",
                          "variant_title": "60s x 1"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktokshop",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1507,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "product",
                          "id": "1729477768109462617",
                          "url": "https://shop.tiktok.com/us/pdp/1729477768109462617"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokshopReviewsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Star ratings, text and photos for a product",
        "tags": [
          "TikTok Shop"
        ],
        "x-socialtap-endpoint": "tiktokshop.reviews",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "TikTok Shop's recommended order (the order its product page shows reviews in)",
          "page_max": 5,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "review",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tiktokshop/search_products": {
      "get": {
        "description": "Searches TikTok Shop's US products by keyword and returns them in TikTok Shop's relevance order, a page at a time. Each has its link, title, image, price with the price before discount and the highest variant price, units sold, rating and review count, brand, free shipping, and the shop selling it with its storefront link and verified badge.\n\nReturns `{data, page, meta}`: `data` holds up to 30 `Product` items (the shared schema, the same on every platform), TikTok Shop's relevance order. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/tiktokshop/search_products/ (Markdown: https://socialtap.dev/docs/reference/tiktokshop/search_products/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/tiktokshop/search_products/index.md)",
          "url": "https://socialtap.dev/docs/reference/tiktokshop/search_products/"
        },
        "operationId": "tiktokshop.search_products.list",
        "parameters": [
          {
            "description": "Keywords, matched by TikTok Shop's product search against product titles, brands and shops (case-insensitive).",
            "example": "ashwagandha",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Keywords, matched by TikTok Shop's product search against product titles, brands and shops (case-insensitive).",
              "examples": [
                "ashwagandha"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 30,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 30,
              "maximum": 30,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "platform_specific.tiktokshop.rating"
                          ],
                          "attributes": [],
                          "availability": null,
                          "category": null,
                          "category_id": null,
                          "condition": null,
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "1729488739201226090",
                          "max_price": 32.49,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 2560,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p16-oec-general-useast8.ttcdn-us.com/tos-useast8-i-rt0ujvrtvp-tx2/91d95713b57c4b4d950fa875926735cd~tplv-fhlh96nyum-crop-webp:2560:2560.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=a6e80448&idc=useast5&from=2378011839",
                              "width": 2560
                            }
                          ],
                          "original_price": null,
                          "platform": "tiktokshop",
                          "platform_specific": {
                            "tiktokshop": {
                              "brand": "youtheory",
                              "delivery_max_days": null,
                              "delivery_min_days": null,
                              "metrics": {
                                "rating_distribution": null,
                                "review_count": 37,
                                "sold_count": 229,
                                "stock_count": null
                              },
                              "rating": 4.6,
                              "shop": null,
                              "variants": []
                            }
                          },
                          "price": 32.49,
                          "seller": {
                            "avatar_url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/cc8c449d5a9c4cc59d3dfafb39a92a97~tplv-fhlh96nyum-resize-png:300:300.png?dr=12184&t=555f072d&ps=933b5bde&shp=905da467&shcp=d9d491bf&idc=useast5&from=2422056039",
                            "display_name": "youtheory",
                            "id": "7496211336786708842",
                            "is_verified": true,
                            "url": "https://shop.tiktok.com/us/store/youtheory/7496211336786708842",
                            "username": null
                          },
                          "shipping": {
                            "fee": 0,
                            "is_offered": true
                          },
                          "thumbnail_url": "https://p16-oec-general-useast8.ttcdn-us.com/tos-useast8-i-rt0ujvrtvp-tx2/91d95713b57c4b4d950fa875926735cd~tplv-fhlh96nyum-crop-webp:2560:2560.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=a6e80448&idc=useast5&from=2378011839",
                          "title": "YOUTHEORY Ashwagandha Supplement Capsules 60 Count - KSM-66 Ashwagandha + GABA, Organic Ginger, Adaptogen Stress Relief, Clinically Supported, Dietary Botanical, GMP-Certified Vegetarian Capsules",
                          "type": "product",
                          "unknown_fields": [
                            "attributes",
                            "platform_specific.tiktokshop.variants"
                          ],
                          "url": "https://shop.tiktok.com/us/pdp/1729488739201226090"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.tiktokshop.rating"
                          ],
                          "attributes": [],
                          "availability": null,
                          "category": null,
                          "category_id": null,
                          "condition": null,
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "1732757061224141233",
                          "max_price": 19.99,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 1000,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/b7e7126391b2411c860c7c38a7a7fc7a~tplv-fhlh96nyum-crop-webp:1000:1000.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=a6e80448&idc=useast5&from=2378011839",
                              "width": 1000
                            }
                          ],
                          "original_price": null,
                          "platform": "tiktokshop",
                          "platform_specific": {
                            "tiktokshop": {
                              "brand": null,
                              "delivery_max_days": null,
                              "delivery_min_days": null,
                              "metrics": {
                                "rating_distribution": null,
                                "review_count": 1,
                                "sold_count": 38,
                                "stock_count": null
                              },
                              "rating": 4,
                              "shop": null,
                              "variants": []
                            }
                          },
                          "price": 11.99,
                          "seller": {
                            "avatar_url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/26b624d17d3b475ca8f44b668af47c9e~tplv-fhlh96nyum-resize-png:300:300.png?dr=12184&t=555f072d&ps=933b5bde&shp=905da467&shcp=d9d491bf&idc=useast5&from=2422056039",
                            "display_name": "Robesan Shop",
                            "id": "7496000556813355441",
                            "is_verified": false,
                            "url": "https://shop.tiktok.com/us/store/robesan-shop/7496000556813355441",
                            "username": null
                          },
                          "shipping": {
                            "fee": 0,
                            "is_offered": true
                          },
                          "thumbnail_url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/b7e7126391b2411c860c7c38a7a7fc7a~tplv-fhlh96nyum-crop-webp:1000:1000.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=a6e80448&idc=useast5&from=2378011839",
                          "title": "Bunkell Ashwagandha Health Supplements,Supports endurance and performance,60 Capsules",
                          "type": "product",
                          "unknown_fields": [
                            "attributes",
                            "platform_specific.tiktokshop.variants"
                          ],
                          "url": "https://shop.tiktok.com/us/pdp/1732757061224141233"
                        },
                        {
                          "approximate_fields": [
                            "platform_specific.tiktokshop.rating"
                          ],
                          "attributes": [],
                          "availability": null,
                          "category": null,
                          "category_id": null,
                          "condition": null,
                          "condition_label": null,
                          "country_code": "US",
                          "currency": "USD",
                          "description": null,
                          "id": "1730657812285330093",
                          "max_price": 38.94,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 1500,
                              "thumbnail_url": null,
                              "type": "image",
                              "url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/f72f80945ed94f2399d67c0767586060~tplv-fhlh96nyum-crop-webp:1500:1500.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=a6e80448&idc=useast5&from=2378011839",
                              "width": 1500
                            }
                          ],
                          "original_price": 26.95,
                          "platform": "tiktokshop",
                          "platform_specific": {
                            "tiktokshop": {
                              "brand": "Micro Ingredients",
                              "delivery_max_days": null,
                              "delivery_min_days": null,
                              "metrics": {
                                "rating_distribution": null,
                                "review_count": 2857,
                                "sold_count": 28428,
                                "stock_count": null
                              },
                              "rating": 4.8,
                              "shop": null,
                              "variants": []
                            }
                          },
                          "price": 19.95,
                          "seller": {
                            "avatar_url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/5959296c496c421791fa78fa45cfd017~tplv-fhlh96nyum-resize-png:300:300.png?dr=12184&t=555f072d&ps=933b5bde&shp=905da467&shcp=d9d491bf&idc=useast5&from=2422056039",
                            "display_name": "Micro Ingredients",
                            "id": "7494949083499694765",
                            "is_verified": true,
                            "url": "https://shop.tiktok.com/us/store/micro-ingredients/7494949083499694765",
                            "username": null
                          },
                          "shipping": {
                            "fee": 0,
                            "is_offered": true
                          },
                          "thumbnail_url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/f72f80945ed94f2399d67c0767586060~tplv-fhlh96nyum-crop-webp:1500:1500.webp?dr=12190&t=555f072d&ps=933b5bde&shp=8dbd94bf&shcp=a6e80448&idc=useast5&from=2378011839",
                          "title": "Micro Ingredients Ashwagandha + Black Pepper Extract with MCT Oil Softgels",
                          "type": "product",
                          "unknown_fields": [
                            "attributes",
                            "platform_specific.tiktokshop.variants"
                          ],
                          "url": "https://shop.tiktok.com/us/pdp/1730657812285330093"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "tiktokshop",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 882,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TiktokshopSearch_productsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Products by keyword, with price and units sold",
        "tags": [
          "TikTok Shop"
        ],
        "x-socialtap-endpoint": "tiktokshop.search_products",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "TikTok Shop's relevance order",
          "page_max": 30,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "product",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/tool_runs": {
      "post": {
        "description": "What the site's free tools send: one lookup on an endpoint that has a free tool, with no account. Not for API clients: limited per IP address and behind a bot check. The same data with an API key has no such limits.\n\n**Auth:** none.",
        "operationId": "tool_runs.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "fresh": {
                    "description": "Skip the cache (counts as a lookup).",
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "input": {
                    "description": "What the visitor typed: the value of the endpoint's identifying param.",
                    "maxLength": 2048,
                    "type": "string"
                  },
                  "token": {
                    "description": "The page's Cloudflare Turnstile response, required where the bot check is set up.",
                    "maxLength": 2048,
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "tool": {
                    "description": "The tool's slug (its page is /tools/<slug>/).",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "endpoint": {
                          "description": "The endpoint it ran (its catalog ID).",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always tool_run.",
                          "enum": [
                            "tool_run"
                          ],
                          "type": "string"
                        },
                        "remaining": {
                          "description": "What is left of this address's free lookups.",
                          "properties": {
                            "day": {
                              "description": "Lookups left today.",
                              "type": "integer"
                            },
                            "hour": {
                              "description": "Lookups left this hour.",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "hour",
                            "day"
                          ],
                          "type": "object"
                        },
                        "result": {
                          "description": "The endpoint's response, exactly as the API returns it to an API key: its data and meta."
                        },
                        "tool": {
                          "description": "The tool's slug.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "tool",
                        "endpoint",
                        "result",
                        "remaining"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Run a free tool",
            "headers": {
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [],
        "summary": "Run a free tool",
        "tags": [
          "Docs"
        ],
        "x-socialtap-auth": {
          "auth": "none",
          "role": "",
          "scope": ""
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/truthsocial/post": {
      "get": {
        "description": "Returns one public Truth Social post, a Truth or a ReTruth, from any of its links or its ID, with exact reply, ReTruth and like counts. It also has the text with hashtags and mentions, images and videos with their alt text, link card, poll, publish and edit times, the author with the verified badge, the group it was posted in (where it also has downvotes), and the post it replies to, quotes or ReTruths.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/truthsocial/post/ (Markdown: https://socialtap.dev/docs/reference/truthsocial/post/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/truthsocial/post/index.md)",
          "url": "https://socialtap.dev/docs/reference/truthsocial/post/"
        },
        "operationId": "truthsocial.post.get",
        "parameters": [
          {
            "description": "The post: its link (truthsocial.com/@realDonaldTrump/117554198887656582), the share link (/@<name>/posts/<id>), either with /embed or /history, the ActivityPub link (/users/<name>/statuses/<id>), a group post's link (/group/<slug>/posts/<id>), /statuses/<id>, /embed/<id>, or the bare post ID.",
            "example": "https://truthsocial.com/@realDonaldTrump/117554198887656582",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The post: its link (truthsocial.com/@realDonaldTrump/117554198887656582), the share link (/@<name>/posts/<id>), either with /embed or /history, the ActivityPub link (/users/<name>/statuses/<id>), a group post's link (/group/<slug>/posts/<id>), /statuses/<id>, /embed/<id>, or the bare post ID.",
              "examples": [
                "https://truthsocial.com/@realDonaldTrump/117554198887656582"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/accounts/avatars/107/780/257/626/128/497/original/454286ac07a6f6e6.jpeg",
                          "display_name": "Donald J. Trump",
                          "id": "107780257626128497",
                          "is_verified": true,
                          "url": "https://truthsocial.com/@realDonaldTrump",
                          "username": "realDonaldTrump"
                        },
                        "coauthors": [],
                        "duration_ms": null,
                        "hashtags": [],
                        "id": "117554198887656582",
                        "is_nsfw": false,
                        "is_pinned": null,
                        "is_sponsored": false,
                        "language": "en",
                        "media": [],
                        "mentions": [],
                        "metrics": {
                          "comment_count": 767,
                          "like_count": 7300,
                          "quote_count": null,
                          "repost_count": 2068,
                          "save_count": null,
                          "share_count": null,
                          "view_count": null
                        },
                        "platform": "truthsocial",
                        "platform_specific": {
                          "truthsocial": {
                            "downvote_count": null,
                            "edited_at": null,
                            "group": null,
                            "link": null,
                            "poll": null,
                            "quoted_post": null,
                            "reblog_of": null,
                            "reply_to": null
                          }
                        },
                        "platform_type": "truth",
                        "published_at": "2026-11-03T19:38:44Z",
                        "text": "The Jewish community in Monsey, New York, and its surrounding neighborhoods, voted in very big numbers for me in our Historic 2024 Presidential Campaign. TREMENDOUS SUPPORT!\n\nTODAY, the eyes of the Country are on New York again!\n\nCongressman Mike Lawler has been a tremendous frie…",
                        "thumbnail_url": null,
                        "title": null,
                        "type": "text",
                        "unknown_fields": [],
                        "url": "https://truthsocial.com/@realDonaldTrump/117554198887656582"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "truthsocial",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 168,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "117554198887656582",
                          "url": "https://truthsocial.com/@realDonaldTrump/117554198887656582"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TruthsocialPostResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Truth or ReTruth with exact reply and like counts",
        "tags": [
          "Truth Social"
        ],
        "x-socialtap-endpoint": "truthsocial.post",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/truthsocial/posts": {
      "get": {
        "description": "Returns a Truth Social account's public posts, its Truths and ReTruths, newest first and a page at a time, from a username, profile link or account ID. Each post has its text with hashtags and mentions, images and videos, link card, poll and group, exact publish time, and exact reply, ReTruth and like counts (and downvotes in a group). A ReTruth carries the post it reposts, and a quote the post it quotes.\n\nReturns `{data, page, meta}`: `data` holds up to 20 `Post` items (the shared schema, the same on every platform), newest first. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/truthsocial/posts/ (Markdown: https://socialtap.dev/docs/reference/truthsocial/posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/truthsocial/posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/truthsocial/posts/"
        },
        "operationId": "truthsocial.posts.list",
        "parameters": [
          {
            "description": "The Truth Social account: a username with or without the @ (realDonaldTrump, any case), a profile link (truthsocial.com/@realDonaldTrump, any tab of it, or truthsocial.com/users/realDonaldTrump), or the account's numeric ID as the API writes it (107780257626128497), which saves the name lookup.",
            "example": "realDonaldTrump",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Truth Social account: a username with or without the @ (realDonaldTrump, any case), a profile link (truthsocial.com/@realDonaldTrump, any tab of it, or truthsocial.com/users/realDonaldTrump), or the account's numeric ID as the API writes it (107780257626128497), which saves the name lookup.",
              "examples": [
                "realDonaldTrump"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. A ReTruth counts from when it was ReTruthed.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. A ReTruth counts from when it was ReTruthed.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 20,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/accounts/avatars/107/780/257/626/128/497/original/454286ac07a6f6e6.jpeg",
                            "display_name": "Donald J. Trump",
                            "id": "107780257626128497",
                            "is_verified": true,
                            "url": "https://truthsocial.com/@realDonaldTrump",
                            "username": "realDonaldTrump"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "117554563852726181",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": null,
                              "expires_at": null,
                              "height": 872,
                              "thumbnail_url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/media_attachments/files/117/554/563/634/222/330/small/769b80bb1016bd7c.png",
                              "type": "image",
                              "url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/media_attachments/files/117/554/563/634/222/330/original/769b80bb1016bd7c.png",
                              "width": 882
                            }
                          ],
                          "mentions": [
                            "realDonaldTrump"
                          ],
                          "metrics": {
                            "comment_count": 64,
                            "like_count": 497,
                            "quote_count": null,
                            "repost_count": 194,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "truthsocial",
                          "platform_specific": {
                            "truthsocial": {
                              "downvote_count": null,
                              "edited_at": null,
                              "group": null,
                              "link": null,
                              "poll": null,
                              "quoted_post": {
                                "author": {
                                  "avatar_url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/accounts/avatars/107/780/257/626/128/497/original/454286ac07a6f6e6.jpeg",
                                  "display_name": "Donald J. Trump",
                                  "id": "107780257626128497",
                                  "is_verified": true,
                                  "url": "https://truthsocial.com/@realDonaldTrump",
                                  "username": "realDonaldTrump"
                                },
                                "downvote_count": null,
                                "id": "117554562841729326",
                                "metrics": {
                                  "comment_count": 17,
                                  "like_count": 209,
                                  "quote_count": null,
                                  "repost_count": 80,
                                  "save_count": null,
                                  "share_count": null,
                                  "view_count": null
                                },
                                "published_at": "2026-11-03T21:11:17Z",
                                "url": "https://truthsocial.com/@realDonaldTrump/117554562841729326"
                              },
                              "reblog_of": null,
                              "reply_to": null
                            }
                          },
                          "platform_type": "truth",
                          "published_at": "2026-11-03T21:11:33Z",
                          "text": null,
                          "thumbnail_url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/media_attachments/files/117/554/563/634/222/330/small/769b80bb1016bd7c.png",
                          "title": null,
                          "type": "image",
                          "unknown_fields": [],
                          "url": "https://truthsocial.com/@realDonaldTrump/117554563852726181"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/accounts/avatars/107/780/257/626/128/497/original/454286ac07a6f6e6.jpeg",
                            "display_name": "Donald J. Trump",
                            "id": "107780257626128497",
                            "is_verified": true,
                            "url": "https://truthsocial.com/@realDonaldTrump",
                            "username": "realDonaldTrump"
                          },
                          "coauthors": [],
                          "duration_ms": 278200,
                          "hashtags": [],
                          "id": "117554562841729326",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 278200,
                              "expires_at": null,
                              "height": 720,
                              "thumbnail_url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/media_attachments/thumbnails/117/554/562/311/771/885/original/0b8d2fd60e6c993c.jpg",
                              "type": "video",
                              "url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/media_attachments/files/117/554/562/311/771/885/original/916a7595bd30d5d7.mp4",
                              "width": 1280
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 17,
                            "like_count": 209,
                            "quote_count": null,
                            "repost_count": 80,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "truthsocial",
                          "platform_specific": {
                            "truthsocial": {
                              "downvote_count": null,
                              "edited_at": null,
                              "group": null,
                              "link": null,
                              "poll": null,
                              "quoted_post": null,
                              "reblog_of": null,
                              "reply_to": null
                            }
                          },
                          "platform_type": "truth",
                          "published_at": "2026-11-03T21:11:17Z",
                          "text": null,
                          "thumbnail_url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/media_attachments/thumbnails/117/554/562/311/771/885/original/0b8d2fd60e6c993c.jpg",
                          "title": null,
                          "type": "video",
                          "unknown_fields": [],
                          "url": "https://truthsocial.com/@realDonaldTrump/117554562841729326"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/accounts/avatars/107/780/257/626/128/497/original/454286ac07a6f6e6.jpeg",
                            "display_name": "Donald J. Trump",
                            "id": "107780257626128497",
                            "is_verified": true,
                            "url": "https://truthsocial.com/@realDonaldTrump",
                            "username": "realDonaldTrump"
                          },
                          "coauthors": [],
                          "duration_ms": null,
                          "hashtags": [],
                          "id": "117554198887656582",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": false,
                          "language": "en",
                          "media": [],
                          "mentions": [],
                          "metrics": {
                            "comment_count": 664,
                            "like_count": 5543,
                            "quote_count": null,
                            "repost_count": 1648,
                            "save_count": null,
                            "share_count": null,
                            "view_count": null
                          },
                          "platform": "truthsocial",
                          "platform_specific": {
                            "truthsocial": {
                              "downvote_count": null,
                              "edited_at": null,
                              "group": null,
                              "link": null,
                              "poll": null,
                              "quoted_post": null,
                              "reblog_of": null,
                              "reply_to": null
                            }
                          },
                          "platform_type": "truth",
                          "published_at": "2026-11-03T19:38:44Z",
                          "text": "The Jewish community in Monsey, New York, and its surrounding neighborhoods, voted in very big numbers for me in our Historic 2024 Presidential Campaign. TREMENDOUS SUPPORT!\n\nTODAY, the eyes of the Country are on New York again!\n\nCongressman Mike Lawler has been a tremendous frie…",
                          "thumbnail_url": null,
                          "title": null,
                          "type": "text",
                          "unknown_fields": [],
                          "url": "https://truthsocial.com/@realDonaldTrump/117554198887656582"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "truthsocial",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 710,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "107780257626128497",
                          "url": "https://truthsocial.com/@realDonaldTrump"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TruthsocialPostsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Truths and ReTruths of any account, newest first",
        "tags": [
          "Truth Social"
        ],
        "x-socialtap-endpoint": "truthsocial.posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "page_max": 20,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/truthsocial/profile": {
      "get": {
        "description": "Returns a public Truth Social profile from a username, profile link or account ID, with exact follower, following and post counts. It also has the display name, plain-text bio, website and bio links, avatar and banner, verified badge, location, join date and the day of the latest post, and whether the account is private, a bot, premium or open to direct messages.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/truthsocial/profile/ (Markdown: https://socialtap.dev/docs/reference/truthsocial/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/truthsocial/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/truthsocial/profile/"
        },
        "operationId": "truthsocial.profile.get",
        "parameters": [
          {
            "description": "The Truth Social account: a username with or without the @ (realDonaldTrump, any case), a profile link (truthsocial.com/@realDonaldTrump, any tab of it, or truthsocial.com/users/realDonaldTrump), or the account's numeric ID as the API writes it (107780257626128497).",
            "example": "realDonaldTrump",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Truth Social account: a username with or without the @ (realDonaldTrump, any case), a profile link (truthsocial.com/@realDonaldTrump, any tab of it, or truthsocial.com/users/realDonaldTrump), or the account's numeric ID as the API writes it (107780257626128497).",
              "examples": [
                "realDonaldTrump"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "platform_specific.truthsocial.last_post_at"
                        ],
                        "avatar_url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/accounts/avatars/107/780/257/626/128/497/original/454286ac07a6f6e6.jpeg",
                        "banner_url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/accounts/headers/107/780/257/626/128/497/original/ba3b910ba387bf4e.jpeg",
                        "bio": null,
                        "category": null,
                        "country_code": null,
                        "created_at": "2022-02-11T16:16:57Z",
                        "display_name": "Donald J. Trump",
                        "external_links": [
                          {
                            "title": null,
                            "url": "https://www.DonaldJTrump.com"
                          }
                        ],
                        "id": "107780257626128497",
                        "is_private": false,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 13145535,
                          "following_count": 67,
                          "post_count": 38307,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "truthsocial",
                        "platform_specific": {
                          "truthsocial": {
                            "is_accepting_messages": false,
                            "is_bot": false,
                            "is_discoverable": null,
                            "is_premium": true,
                            "last_post_at": "2026-11-03T00:00:00Z"
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://truthsocial.com/@realDonaldTrump",
                        "username": "realDonaldTrump"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "truthsocial",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 547,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "107780257626128497",
                          "url": "https://truthsocial.com/@realDonaldTrump"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TruthsocialProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact follower counts, bio, links and join date",
        "tags": [
          "Truth Social"
        ],
        "x-socialtap-endpoint": "truthsocial.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/twitch/profile": {
      "get": {
        "description": "Returns a public Twitch channel from its login, link or numeric ID, with its bio, exact followers and whether it is live now. A live channel adds its stream title, category, tags and viewer count. You also get its display name, avatar, banner and offline image, the links it lists, its Partner or Affiliate status, creation date, video count, latest broadcast, and the title, category and language it has set.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\nIn Twitch's words: `is_verified` is Partner badge, `metrics.post_count` is videos.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/twitch/profile/ (Markdown: https://socialtap.dev/docs/reference/twitch/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/twitch/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/twitch/profile/"
        },
        "operationId": "twitch.profile.get",
        "parameters": [
          {
            "description": "The Twitch channel: its login with or without the @ (ninja), a channel link (twitch.tv/ninja), or its numeric ID (19571641). A bare number is read as the ID: a login of digits only is written with its @ (@12345).",
            "example": "ninja",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Twitch channel: its login with or without the @ (ninja), a channel link (twitch.tv/ninja), or its numeric ID (19571641). A bare number is read as the ID: a login of digits only is written with its @ (@12345).",
              "examples": [
                "ninja"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://static-cdn.jtvnw.net/jtv_user_pictures/90d40495-f467-4911-9035-72d8d10a49c5-profile_image-600x600.png",
                        "banner_url": "https://static-cdn.jtvnw.net/jtv_user_pictures/36b341d1-0ee2-4cb2-ae00-361740b0051d-profile_banner-480.png",
                        "bio": "Just want to make people happy. Co-Founder @DrinkNutcase.",
                        "category": "Just Chatting",
                        "country_code": null,
                        "created_at": "2011-01-16T04:31:20Z",
                        "display_name": "Ninja",
                        "external_links": [
                          {
                            "title": "Instagram",
                            "url": "https://www.instagram.com/ninja"
                          },
                          {
                            "title": "X",
                            "url": "https://x.com/ninja"
                          },
                          {
                            "title": "TikTok",
                            "url": "https://www.tiktok.com/@ninja"
                          }
                        ],
                        "id": "19571641",
                        "is_private": false,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 19227283,
                          "following_count": null,
                          "post_count": 1396,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "twitch",
                        "platform_specific": {
                          "twitch": {
                            "category": {
                              "box_art_url": "https://static-cdn.jtvnw.net/ttv-boxart/509658-285x380.jpg",
                              "id": "509658",
                              "name": "Just Chatting",
                              "slug": "just-chatting"
                            },
                            "channel_title": "BLEV BROS SPORTS SHOW WEEK 8 RECAP | GO LIONS | PRAYERS FOR JACK CAMPBELL",
                            "concurrent_viewer_count": null,
                            "is_affiliate": false,
                            "is_live": false,
                            "is_mature": false,
                            "language": "en",
                            "last_broadcast": {
                              "category": {
                                "box_art_url": "https://static-cdn.jtvnw.net/ttv-boxart/509658-285x380.jpg",
                                "id": "509658",
                                "name": "Just Chatting",
                                "slug": "just-chatting"
                              },
                              "id": "322129789658",
                              "started_at": "2026-11-04T03:43:53Z",
                              "title": "BLEV BROS SPORTS SHOW WEEK 8 RECAP | GO LIONS | PRAYERS FOR JACK CAMPBELL"
                            },
                            "offline_image_url": "https://static-cdn.jtvnw.net/jtv_user_pictures/6d03c501-0b93-4c15-b11e-880a2e1db4d1-channel_offline_image-1920x1080.png",
                            "primary_color_hex": "1F69FF",
                            "stream": null,
                            "team": null
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://www.twitch.tv/ninja",
                        "username": "ninja"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "twitch",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 308,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "19571641",
                          "url": "https://www.twitch.tv/ninja"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TwitchProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Channel with exact followers and live status",
        "tags": [
          "Twitch"
        ],
        "x-socialtap-endpoint": "twitch.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/twitch/schedule": {
      "get": {
        "description": "Returns the streams a public Twitch channel has scheduled and not yet started, soonest first, from its login, link or numeric ID. Each slot has its title, category, start and end time, whether it was cancelled and how often it repeats, with the channel's numeric ID, login, name and Partner badge. Each page covers a week.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Live` items (the shared schema, the same on every platform), Soonest first, a week per page. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/twitch/schedule/ (Markdown: https://socialtap.dev/docs/reference/twitch/schedule/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/twitch/schedule/index.md)",
          "url": "https://socialtap.dev/docs/reference/twitch/schedule/"
        },
        "operationId": "twitch.schedule.list",
        "parameters": [
          {
            "description": "The Twitch channel: its login with or without the @ (riotgames), a channel link (twitch.tv/riotgames/schedule), or its numeric ID (36029255). A bare number is read as the ID: a login of digits only is written with its @ (@12345).",
            "example": "riotgames",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Twitch channel: its login with or without the @ (riotgames), a channel link (twitch.tv/riotgames/schedule), or its numeric ID (36029255). A bare number is read as the ID: a login of digits only is written with its @ (@12345).",
              "examples": [
                "riotgames"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "category": "League of Legends",
                          "ended_at": null,
                          "host": {
                            "avatar_url": "https://static-cdn.jtvnw.net/jtv_user_pictures/35b02a12-d516-499e-90f8-7899f136fa18-profile_image-300x300.png",
                            "display_name": "Riot Games",
                            "id": "36029255",
                            "is_verified": true,
                            "url": "https://www.twitch.tv/riotgames",
                            "username": "riotgames"
                          },
                          "id": "eyJzZWdtZW50SUQiOiJiYmQ2OGYxOC03MTYwLTRjYjgtODdmOC1mY2Y1NDZiN2FmMjYiLCJpc29ZZWFyIjoyMDI2LCJpc29XZWVrIjo0NX0=",
                          "metrics": {
                            "concurrent_viewer_count": null,
                            "like_count": null,
                            "view_count": null
                          },
                          "platform": "twitch",
                          "platform_specific": {
                            "twitch": {
                              "base_segment_id": "bbd68f18-7160-4cb8-87f8-fcf546b7af26",
                              "cancellation_ends_at": null,
                              "categories": [
                                {
                                  "box_art_url": "https://static-cdn.jtvnw.net/ttv-boxart/21779-285x380.jpg",
                                  "id": "21779",
                                  "name": "League of Legends",
                                  "slug": "league-of-legends"
                                }
                              ],
                              "is_cancelled": false,
                              "repeat_ends_after_count": 1,
                              "scheduled_end_at": "2026-11-06T06:30:00Z",
                              "vacation": null
                            }
                          },
                          "post_id": null,
                          "scheduled_start_at": "2026-11-05T20:30:00Z",
                          "started_at": null,
                          "status": "scheduled",
                          "streams": [],
                          "text": null,
                          "thumbnail_url": null,
                          "title": "Worlds 2026 | Knockout Stage Day 3",
                          "unknown_fields": [],
                          "url": "https://www.twitch.tv/riotgames/schedule"
                        },
                        {
                          "approximate_fields": [],
                          "category": "League of Legends",
                          "ended_at": null,
                          "host": {
                            "avatar_url": "https://static-cdn.jtvnw.net/jtv_user_pictures/35b02a12-d516-499e-90f8-7899f136fa18-profile_image-300x300.png",
                            "display_name": "Riot Games",
                            "id": "36029255",
                            "is_verified": true,
                            "url": "https://www.twitch.tv/riotgames",
                            "username": "riotgames"
                          },
                          "id": "eyJzZWdtZW50SUQiOiI0NDExNTQwOC1iZDYyLTRkZjktOTVmYy1iYTRiNzFjM2NhMDYiLCJpc29ZZWFyIjoyMDI2LCJpc29XZWVrIjo0NX0=",
                          "metrics": {
                            "concurrent_viewer_count": null,
                            "like_count": null,
                            "view_count": null
                          },
                          "platform": "twitch",
                          "platform_specific": {
                            "twitch": {
                              "base_segment_id": "44115408-bd62-4df9-95fc-ba4b71c3ca06",
                              "cancellation_ends_at": null,
                              "categories": [
                                {
                                  "box_art_url": "https://static-cdn.jtvnw.net/ttv-boxart/21779-285x380.jpg",
                                  "id": "21779",
                                  "name": "League of Legends",
                                  "slug": "league-of-legends"
                                }
                              ],
                              "is_cancelled": false,
                              "repeat_ends_after_count": 1,
                              "scheduled_end_at": "2026-11-07T06:30:00Z",
                              "vacation": null
                            }
                          },
                          "post_id": null,
                          "scheduled_start_at": "2026-11-06T20:30:00Z",
                          "started_at": null,
                          "status": "scheduled",
                          "streams": [],
                          "text": null,
                          "thumbnail_url": null,
                          "title": "Worlds 2026 | Knockout Stage Day 4",
                          "unknown_fields": [],
                          "url": "https://www.twitch.tv/riotgames/schedule"
                        },
                        {
                          "approximate_fields": [],
                          "category": "League of Legends",
                          "ended_at": null,
                          "host": {
                            "avatar_url": "https://static-cdn.jtvnw.net/jtv_user_pictures/35b02a12-d516-499e-90f8-7899f136fa18-profile_image-300x300.png",
                            "display_name": "Riot Games",
                            "id": "36029255",
                            "is_verified": true,
                            "url": "https://www.twitch.tv/riotgames",
                            "username": "riotgames"
                          },
                          "id": "eyJzZWdtZW50SUQiOiI4MDAzOGYzMC04Y2QzLTQ5ZGYtODhjYi1kMmJkZmViYWQ0MGUiLCJpc29ZZWFyIjoyMDI2LCJpc29XZWVrIjo0NX0=",
                          "metrics": {
                            "concurrent_viewer_count": null,
                            "like_count": null,
                            "view_count": null
                          },
                          "platform": "twitch",
                          "platform_specific": {
                            "twitch": {
                              "base_segment_id": "80038f30-8cd3-49df-88cb-d2bdfebad40e",
                              "cancellation_ends_at": null,
                              "categories": [
                                {
                                  "box_art_url": "https://static-cdn.jtvnw.net/ttv-boxart/21779-285x380.jpg",
                                  "id": "21779",
                                  "name": "League of Legends",
                                  "slug": "league-of-legends"
                                }
                              ],
                              "is_cancelled": false,
                              "repeat_ends_after_count": 1,
                              "scheduled_end_at": "2026-11-08T06:30:00Z",
                              "vacation": null
                            }
                          },
                          "post_id": null,
                          "scheduled_start_at": "2026-11-07T20:30:00Z",
                          "started_at": null,
                          "status": "scheduled",
                          "streams": [],
                          "text": null,
                          "thumbnail_url": null,
                          "title": "Worlds 2026 | Knockout Stage Day 5",
                          "unknown_fields": [],
                          "url": "https://www.twitch.tv/riotgames/schedule"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "twitch",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 287,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "36029255",
                          "url": "https://www.twitch.tv/riotgames"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TwitchScheduleResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Upcoming streams a channel has announced",
        "tags": [
          "Twitch"
        ],
        "x-socialtap-endpoint": "twitch.schedule",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "Soonest first, a week per page",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "live",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/twitch/transcript": {
      "get": {
        "description": "Returns the timed transcript of a public Twitch clip from any of its links or its slug, transcribed from the clip's audio. Each segment has its start and end time, with the full text, the language heard and the clip's length.\n\nReturns `{data, meta}`: `data` is a `Transcript` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 2 credits + 2 per started minute of media per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/twitch/transcript/ (Markdown: https://socialtap.dev/docs/reference/twitch/transcript/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/twitch/transcript/index.md)",
          "url": "https://socialtap.dev/docs/reference/twitch/transcript/"
        },
        "operationId": "twitch.transcript.get",
        "parameters": [
          {
            "description": "The clip: its link (clips.twitch.tv/<slug>, twitch.tv/<channel>/clip/<slug>, m.twitch.tv/clip/<slug>, clips.twitch.tv/embed?clip=<slug>) or its slug. Links of past broadcasts, highlights and uploads are refused.",
            "example": "https://www.twitch.tv/ninja/clip/IcyBreakableDelicataTooSpicy-RnrKLybQI3W9K_AD",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The clip: its link (clips.twitch.tv/<slug>, twitch.tv/<channel>/clip/<slug>, m.twitch.tv/clip/<slug>, clips.twitch.tv/embed?clip=<slug>) or its slug. Links of past broadcasts, highlights and uploads are refused.",
              "examples": [
                "https://www.twitch.tv/ninja/clip/IcyBreakableDelicataTooSpicy-RnrKLybQI3W9K_AD"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). A hint to speech-to-text: the language the clip is spoken in. Without it the language is detected; language says which was used. It does not translate.",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). A hint to speech-to-text: the language the clip is spoken in. Without it the language is detected; language says which was used. It does not translate.",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "available_languages": [],
                        "duration_ms": 25000,
                        "id": "IcyBreakableDelicataTooSpicy-RnrKLybQI3W9K_AD",
                        "is_auto_generated": true,
                        "language": "en",
                        "platform": "twitch",
                        "platform_specific": {},
                        "segments": [
                          {
                            "end_ms": 10340,
                            "start_ms": 2320,
                            "text": "shadow thank you so much for that donation let me put you on the board"
                          },
                          {
                            "end_ms": 10740,
                            "start_ms": 10340,
                            "text": "real quick"
                          }
                        ],
                        "source": "asr",
                        "text": "shadow thank you so much for that donation let me put you on the board real quick",
                        "url": "https://www.twitch.tv/ninja/clip/IcyBreakableDelicataTooSpicy-RnrKLybQI3W9K_AD"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "twitch",
                        "source": "asr",
                        "is_cached": false,
                        "credits_charged": 4,
                        "latency_ms": 3858,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "clip",
                          "id": "IcyBreakableDelicataTooSpicy-RnrKLybQI3W9K_AD",
                          "url": "https://www.twitch.tv/ninja/clip/IcyBreakableDelicataTooSpicy-RnrKLybQI3W9K_AD"
                        },
                        "credits_remaining": 9996,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TwitchTranscriptResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "no_transcript": {
                    "$ref": "#/components/examples/no_transcript"
                  },
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.\n\n`no_transcript`: The video or audio exists but has no transcript: no caption track and no speech to transcribe. Do not retry. If the platform offers other languages, try one with lang.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Clip transcript with timestamps, from its audio",
        "tags": [
          "Twitch"
        ],
        "x-socialtap-endpoint": "twitch.transcript",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 122,
          "min_credits": 2,
          "prices": [
            {
              "credits": 2,
              "label": "2 credits + 2 per started minute of media",
              "max": 122,
              "per": 2,
              "source": "asr",
              "unit": "media_minute",
              "unit_max": 60
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "transcript",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/twitch/video": {
      "get": {
        "description": "Returns a public Twitch video (past broadcast, highlight or upload) or clip from its link, number or slug, with its exact views and video files. Both have the title, channel with its Partner badge, date, length, language, category and thumbnail. A video adds its chapters by category, whether it is still recording or kept from logged-out viewers, the date Twitch will delete it and a signed playlist of every quality a logged-out viewer gets. A clip adds a signed MP4 at each quality, its vertical version, the account that made it, the channel's exact followers, and the video and moment it was cut from.\n\nReturns `{data, meta}`: `data` is a `Post` object (Twitch calls it a video) (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/twitch/video/ (Markdown: https://socialtap.dev/docs/reference/twitch/video/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/twitch/video/index.md)",
          "url": "https://socialtap.dev/docs/reference/twitch/video/"
        },
        "operationId": "twitch.video.get",
        "parameters": [
          {
            "description": "The video or clip: its link (twitch.tv/videos/2918964242, twitch.tv/ninja/clip/<slug>, clips.twitch.tv/<slug>, a player or embed link, on any of Twitch's hosts), a video's number (2918964242) or a clip's slug.",
            "example": "https://www.twitch.tv/ninja/clip/IcyBreakableDelicataTooSpicy-RnrKLybQI3W9K_AD",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The video or clip: its link (twitch.tv/videos/2918964242, twitch.tv/ninja/clip/<slug>, clips.twitch.tv/<slug>, a player or embed link, on any of Twitch's hosts), a video's number (2918964242) or a clip's slug.",
              "examples": [
                "https://www.twitch.tv/ninja/clip/IcyBreakableDelicataTooSpicy-RnrKLybQI3W9K_AD"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://static-cdn.jtvnw.net/jtv_user_pictures/90d40495-f467-4911-9035-72d8d10a49c5-profile_image-300x300.png",
                          "display_name": "Ninja",
                          "id": "19571641",
                          "is_verified": true,
                          "url": "https://www.twitch.tv/ninja",
                          "username": "ninja"
                        },
                        "coauthors": [],
                        "duration_ms": 25000,
                        "hashtags": [],
                        "id": "IcyBreakableDelicataTooSpicy-RnrKLybQI3W9K_AD",
                        "is_nsfw": false,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": "en",
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": 25000,
                            "expires_at": "2026-11-06T01:53:39Z",
                            "height": 1080,
                            "thumbnail_url": "https://static-cdn.jtvnw.net/twitch-video-assets/twitch-vap-video-assets-prod-us-west-2/63bd5360-8aea-4234-bce7-00a6426d621a/landscape/thumb/thumb-0000000000-1920x1080.jpg",
                            "type": "video",
                            "url": "https://d1ndex63qxojbr.cloudfront.net/nauth/63bd5360-8aea-4234-bce7-00a6426d621a/landscape/avc/1080/index.mp4?sig=SCRUBBED&token=%7B%22authorization%22%3A%7B%22forbidden%22%3Afalse%2C%22reason%22%3A%22%22%7D%2C%22clip_uri%22%3A%22https%3A%2F%2Fd1ndex63qxojbr.cloudfront.net%2Fnaut…",
                            "width": 1920
                          }
                        ],
                        "mentions": [],
                        "metrics": {
                          "comment_count": null,
                          "like_count": null,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": null,
                          "share_count": null,
                          "view_count": 314763
                        },
                        "platform": "twitch",
                        "platform_specific": {
                          "twitch": {
                            "animated_preview_url": null,
                            "author_follower_count": 19227257,
                            "broadcast_id": "41505484557",
                            "broadcast_type": "clip",
                            "category": {
                              "box_art_url": "https://static-cdn.jtvnw.net/ttv-boxart/509658-285x380.jpg",
                              "id": "509658",
                              "name": "Just Chatting",
                              "slug": "just-chatting"
                            },
                            "chapters": [],
                            "clip_id": "1887094151",
                            "clipped_by": {
                              "avatar_url": "https://static-cdn.jtvnw.net/jtv_user_pictures/6b44b8a3-587a-4ca2-b527-d8b07baae7ef-profile_image-300x300.png",
                              "display_name": "sSaintPablo",
                              "id": "206880681",
                              "is_verified": false,
                              "url": "https://www.twitch.tv/ssaintpablo",
                              "username": "ssaintpablo"
                            },
                            "content_labels": [],
                            "deletes_at": null,
                            "embed_url": "https://clips.twitch.tv/embed?clip=IcyBreakableDelicataTooSpicy-RnrKLybQI3W9K_AD",
                            "is_featured": false,
                            "is_recording": null,
                            "is_restricted": null,
                            "renditions": [
                              {
                                "expires_at": "2026-11-06T01:53:39Z",
                                "frame_rate": null,
                                "quality": "1080",
                                "url": "https://d1ndex63qxojbr.cloudfront.net/nauth/63bd5360-8aea-4234-bce7-00a6426d621a/landscape/avc/1080/index.mp4?sig=SCRUBBED&token=%7B%22authorization%22%3A%7B%22forbidden%22%3Afalse%2C%22reason%22%3A%22%22%7D%2C%22clip_uri%22%3A%22https%3A%2F%2Fd1ndex63qxojbr.cloudfront.net%2Fnaut…"
                              },
                              {
                                "expires_at": "2026-11-06T01:53:39Z",
                                "frame_rate": null,
                                "quality": "720",
                                "url": "https://d1ndex63qxojbr.cloudfront.net/nauth/63bd5360-8aea-4234-bce7-00a6426d621a/landscape/avc/720/index.mp4?sig=SCRUBBED&token=%7B%22authorization%22%3A%7B%22forbidden%22%3Afalse%2C%22reason%22%3A%22%22%7D%2C%22clip_uri%22%3A%22https%3A%2F%2Fd1ndex63qxojbr.cloudfront.net%2Fnauth…"
                              },
                              {
                                "expires_at": "2026-11-06T01:53:39Z",
                                "frame_rate": null,
                                "quality": "480",
                                "url": "https://d1ndex63qxojbr.cloudfront.net/nauth/63bd5360-8aea-4234-bce7-00a6426d621a/landscape/avc/480/index.mp4?sig=SCRUBBED&token=%7B%22authorization%22%3A%7B%22forbidden%22%3Afalse%2C%22reason%22%3A%22%22%7D%2C%22clip_uri%22%3A%22https%3A%2F%2Fd1ndex63qxojbr.cloudfront.net%2Fnauth…"
                              }
                            ],
                            "source_video": {
                              "id": "994448370",
                              "offset_ms": 5206000,
                              "title": "Ninja's April \"Inside Ninja's head\" on Twitch! !ask",
                              "url": "https://www.twitch.tv/videos/994448370"
                            },
                            "vertical_renditions": []
                          }
                        },
                        "platform_type": "clip",
                        "published_at": "2021-04-20T18:22:14Z",
                        "text": null,
                        "thumbnail_url": "https://static-cdn.jtvnw.net/twitch-video-assets/twitch-vap-video-assets-prod-us-west-2/63bd5360-8aea-4234-bce7-00a6426d621a/landscape/thumb/thumb-0000000000-1920x1080.jpg",
                        "title": "Ninja Reenacting Chalk Board Egirls",
                        "type": "video",
                        "unknown_fields": [],
                        "url": "https://www.twitch.tv/ninja/clip/IcyBreakableDelicataTooSpicy-RnrKLybQI3W9K_AD"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "twitch",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 287,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "clip",
                          "id": "IcyBreakableDelicataTooSpicy-RnrKLybQI3W9K_AD",
                          "url": "https://www.twitch.tv/ninja/clip/IcyBreakableDelicataTooSpicy-RnrKLybQI3W9K_AD"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TwitchVideoResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Video or clip with exact views and its video files",
        "tags": [
          "Twitch"
        ],
        "x-socialtap-endpoint": "twitch.video",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/twitch/videos": {
      "get": {
        "description": "Returns a public Twitch channel's past broadcasts, highlights and uploads, newest or most viewed first, from its login, link or numeric ID. Each video has its link, signed playlist, title, description, publish time, length, exact views, language, thumbnail and storyboard, its category, whether it is still recording or kept from logged-out viewers, Twitch's content labels, and the channel that made it.\n\nReturns `{data, page, meta}`: `data` holds up to 100 `Post` items (Twitch calls it a video) (the shared schema, the same on every platform), newest first with sort=newest (the default), Twitch's most viewed first, of all time with sort=popular. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/twitch/videos/ (Markdown: https://socialtap.dev/docs/reference/twitch/videos/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/twitch/videos/index.md)",
          "url": "https://socialtap.dev/docs/reference/twitch/videos/"
        },
        "operationId": "twitch.videos.list",
        "parameters": [
          {
            "description": "The Twitch channel: its login with or without the @ (ninja), a channel link with any tab after it (twitch.tv/ninja/videos), or its numeric ID (19571641). A bare number is read as the ID: a login of digits only is written with its @ (@12345).",
            "example": "ninja",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "The Twitch channel: its login with or without the @ (ninja), a channel link with any tab after it (twitch.tv/ninja/videos), or its numeric ID (19571641). A bare number is read as the ID: a login of digits only is written with its @ (@12345).",
              "examples": [
                "ninja"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Which videos: all (default), archive (past broadcasts), highlight (cut from a broadcast by the channel) or upload. Twitch keeps past broadcasts for a limited time, so a channel can have none.",
            "example": "highlight",
            "in": "query",
            "name": "type",
            "schema": {
              "default": "all",
              "description": "Which videos: all (default), archive (past broadcasts), highlight (cut from a broadcast by the channel) or upload. Twitch keeps past broadcasts for a limited time, so a channel can have none.",
              "enum": [
                "all",
                "archive",
                "highlight",
                "upload"
              ],
              "examples": [
                "highlight"
              ],
              "type": "string"
            }
          },
          {
            "description": "Order of the results. newest (default): the latest video first. popular: the most viewed first, of all time.",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "newest",
              "description": "Order of the results. newest (default): the latest video first. popular: the most viewed first, of all time.",
              "enum": [
                "newest",
                "popular"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only videos published at or after this time. On past broadcasts (type=archive), newest first, the walk ends when it is reached; on anything else it filters the page.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Only videos published at or after this time. On past broadcasts (type=archive), newest first, the walk ends when it is reached; on anything else it filters the page.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Only videos published before this time. It filters the page.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Only videos published before this time. It filters the page.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 100,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://static-cdn.jtvnw.net/jtv_user_pictures/90d40495-f467-4911-9035-72d8d10a49c5-profile_image-300x300.png",
                            "display_name": "Ninja",
                            "id": "19571641",
                            "is_verified": true,
                            "url": "https://www.twitch.tv/ninja",
                            "username": "ninja"
                          },
                          "coauthors": [],
                          "duration_ms": 7726000,
                          "hashtags": [],
                          "id": "2918964242",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 7726000,
                              "expires_at": "2026-11-06T01:53:41Z",
                              "height": null,
                              "thumbnail_url": "https://static-cdn.jtvnw.net/cf_vods/d1m7jfoe9zdc1j/3a618d76bb26843ecc3f_ninja_322129789658_1793756098//thumb/thumb0-1280x720.jpg",
                              "type": "video",
                              "url": "https://usher.ttvnw.net/vod/2918964242.m3u8?allow_audio_only=true&allow_source=true&player=twitchweb&playlist_include_framerate=true&sig=SCRUBBED&token=%7B%22authorization%22%3A%7B%22forbidden%22%3Afalse%2C%22reason%22%3A%22%22%7D%2C%22chansub%22%3A%7B%22restricted_bitrates%22%3A…",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 34782
                          },
                          "platform": "twitch",
                          "platform_specific": {
                            "twitch": {
                              "animated_preview_url": "https://d1m7jfoe9zdc1j.cloudfront.net/3a618d76bb26843ecc3f_ninja_322129789658_1793756098/storyboards/2918964242-strip-0.jpg",
                              "author_follower_count": null,
                              "broadcast_id": null,
                              "broadcast_type": "archive",
                              "category": {
                                "box_art_url": "https://static-cdn.jtvnw.net/ttv-boxart/509658-285x380.jpg",
                                "id": "509658",
                                "name": "Just Chatting",
                                "slug": "just-chatting"
                              },
                              "chapters": [],
                              "clip_id": null,
                              "clipped_by": null,
                              "content_labels": [],
                              "deletes_at": null,
                              "embed_url": null,
                              "is_featured": null,
                              "is_recording": false,
                              "is_restricted": false,
                              "renditions": [],
                              "source_video": null,
                              "vertical_renditions": []
                            }
                          },
                          "platform_type": "live",
                          "published_at": "2026-11-04T01:35:03Z",
                          "text": null,
                          "thumbnail_url": "https://static-cdn.jtvnw.net/cf_vods/d1m7jfoe9zdc1j/3a618d76bb26843ecc3f_ninja_322129789658_1793756098//thumb/thumb0-1280x720.jpg",
                          "title": "BLEV BROS SPORTS SHOW WEEK 8 RECAP | GO LIONS | PRAYERS FOR JACK CAMPBELL",
                          "type": "video",
                          "unknown_fields": [
                            "platform_specific.twitch.chapters"
                          ],
                          "url": "https://www.twitch.tv/videos/2918964242"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://static-cdn.jtvnw.net/jtv_user_pictures/90d40495-f467-4911-9035-72d8d10a49c5-profile_image-300x300.png",
                            "display_name": "Ninja",
                            "id": "19571641",
                            "is_verified": true,
                            "url": "https://www.twitch.tv/ninja",
                            "username": "ninja"
                          },
                          "coauthors": [],
                          "duration_ms": 7641000,
                          "hashtags": [],
                          "id": "2912661812",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 7641000,
                              "expires_at": "2026-11-06T01:53:41Z",
                              "height": null,
                              "thumbnail_url": "https://static-cdn.jtvnw.net/cf_vods/d1m7jfoe9zdc1j/a4420620c79ca00ab677_ninja_321991442137_1793147635//thumb/thumb0-1280x720.jpg",
                              "type": "video",
                              "url": "https://usher.ttvnw.net/vod/2912661812.m3u8?allow_audio_only=true&allow_source=true&player=twitchweb&playlist_include_framerate=true&sig=SCRUBBED&token=%7B%22authorization%22%3A%7B%22forbidden%22%3Afalse%2C%22reason%22%3A%22%22%7D%2C%22chansub%22%3A%7B%22restricted_bitrates%22%3A…",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 53518
                          },
                          "platform": "twitch",
                          "platform_specific": {
                            "twitch": {
                              "animated_preview_url": "https://d1m7jfoe9zdc1j.cloudfront.net/a4420620c79ca00ab677_ninja_321991442137_1793147635/storyboards/2912661812-strip-0.jpg",
                              "author_follower_count": null,
                              "broadcast_id": null,
                              "broadcast_type": "archive",
                              "category": {
                                "box_art_url": "https://static-cdn.jtvnw.net/ttv-boxart/509658-285x380.jpg",
                                "id": "509658",
                                "name": "Just Chatting",
                                "slug": "just-chatting"
                              },
                              "chapters": [],
                              "clip_id": null,
                              "clipped_by": null,
                              "content_labels": [],
                              "deletes_at": null,
                              "embed_url": null,
                              "is_featured": null,
                              "is_recording": false,
                              "is_restricted": false,
                              "renditions": [],
                              "source_video": null,
                              "vertical_renditions": []
                            }
                          },
                          "platform_type": "live",
                          "published_at": "2026-10-28T00:34:00Z",
                          "text": null,
                          "thumbnail_url": "https://static-cdn.jtvnw.net/cf_vods/d1m7jfoe9zdc1j/a4420620c79ca00ab677_ninja_321991442137_1793147635//thumb/thumb0-1280x720.jpg",
                          "title": "BLEV BROS SPORTS SHOW WEEK 7 RECAP",
                          "type": "video",
                          "unknown_fields": [
                            "platform_specific.twitch.chapters"
                          ],
                          "url": "https://www.twitch.tv/videos/2912661812"
                        },
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://static-cdn.jtvnw.net/jtv_user_pictures/90d40495-f467-4911-9035-72d8d10a49c5-profile_image-300x300.png",
                            "display_name": "Ninja",
                            "id": "19571641",
                            "is_verified": true,
                            "url": "https://www.twitch.tv/ninja",
                            "username": "ninja"
                          },
                          "coauthors": [],
                          "duration_ms": 998000,
                          "hashtags": [],
                          "id": "2909042011",
                          "is_nsfw": false,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": "en",
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 998000,
                              "expires_at": "2026-11-06T01:53:41Z",
                              "height": null,
                              "thumbnail_url": "https://static-cdn.jtvnw.net/cf_vods/d1m7jfoe9zdc1j/65503c51b8da69e7b122_ninja_321934738265_1792803422//thumb/thumb0-1280x720.jpg",
                              "type": "video",
                              "url": "https://usher.ttvnw.net/vod/2909042011.m3u8?allow_audio_only=true&allow_source=true&player=twitchweb&playlist_include_framerate=true&sig=SCRUBBED&token=%7B%22authorization%22%3A%7B%22forbidden%22%3Afalse%2C%22reason%22%3A%22%22%7D%2C%22chansub%22%3A%7B%22restricted_bitrates%22%3A…",
                              "width": null
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": null,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 14940
                          },
                          "platform": "twitch",
                          "platform_specific": {
                            "twitch": {
                              "animated_preview_url": "https://d1m7jfoe9zdc1j.cloudfront.net/65503c51b8da69e7b122_ninja_321934738265_1792803422/storyboards/2909042011-strip-0.jpg",
                              "author_follower_count": null,
                              "broadcast_id": null,
                              "broadcast_type": "archive",
                              "category": {
                                "box_art_url": "https://static-cdn.jtvnw.net/ttv-boxart/1264310518_IGDB-285x380.jpg",
                                "id": "1264310518",
                                "name": "Marvel Rivals",
                                "slug": "marvel-rivals"
                              },
                              "chapters": [],
                              "clip_id": null,
                              "clipped_by": null,
                              "content_labels": [],
                              "deletes_at": null,
                              "embed_url": null,
                              "is_featured": null,
                              "is_recording": false,
                              "is_restricted": false,
                              "renditions": [],
                              "source_video": null,
                              "vertical_renditions": []
                            }
                          },
                          "platform_type": "live",
                          "published_at": "2026-10-24T00:57:07Z",
                          "text": null,
                          "thumbnail_url": "https://static-cdn.jtvnw.net/cf_vods/d1m7jfoe9zdc1j/65503c51b8da69e7b122_ninja_321934738265_1792803422//thumb/thumb0-1280x720.jpg",
                          "title": "CHECKING OUT THE BRAND NEW MARVEL RIVALS UPDATE WITH TIMMY TONKA TENDERS",
                          "type": "video",
                          "unknown_fields": [
                            "platform_specific.twitch.chapters"
                          ],
                          "url": "https://www.twitch.tv/videos/2909042011"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "twitch",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 407,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "19571641",
                          "url": "https://www.twitch.tv/ninja"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "platform_limit"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TwitchVideosResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Past broadcasts, highlights and uploads of a channel",
        "tags": [
          "Twitch"
        ],
        "x-socialtap-endpoint": "twitch.videos",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "orders": {
            "newest": "newest first",
            "popular": "Twitch's most viewed first, of all time"
          },
          "page_max": 100,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/usage": {
      "get": {
        "description": "Requests, successes, failures, cache hits, credits charged and the latency of successful requests (p50, p95, and a histogram on request) per time bucket, optionally grouped by endpoint, key, outcome and surface (REST, MCP or a job). Buckets are listed oldest first, cursor-paged. Data is complete to within about 5 minutes; credits reconcile with the ledger. Requests refused before any work (a 402 or 429 with no charge, or while the API was paused) count per account, outcome and surface only: grouped by endpoint or key they have null there, and filtering by endpoint or key leaves them out. spend_limit_reached alone also stays with its key. Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "usage.list",
        "parameters": [
          {
            "description": "Start, inclusive: RFC 3339 or a date (UTC), rounded down to the bucket. Default: 7 buckets before until.",
            "in": "query",
            "name": "since",
            "schema": {
              "maxLength": 40,
              "type": "string"
            }
          },
          {
            "description": "End, exclusive: RFC 3339 or a date (UTC). Default: now.",
            "in": "query",
            "name": "until",
            "schema": {
              "maxLength": 40,
              "type": "string"
            }
          },
          {
            "description": "Bucket size. Default 1d. At most 168 hourly or 31 daily buckets per page.",
            "in": "query",
            "name": "bucket_width",
            "schema": {
              "enum": [
                "1h",
                "1d"
              ],
              "type": "string"
            }
          },
          {
            "description": "Comma-separated subset of endpoint, api_key_id, status, surface: each bucket has one result per combination. Default: one result per bucket.",
            "in": "query",
            "name": "group_by",
            "schema": {
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "description": "Only this endpoint ID (youtube.transcript). Requests refused before any work are left out: they have no endpoint (see Endpoint in the results).",
            "in": "query",
            "name": "endpoint",
            "schema": {
              "maxLength": 100,
              "type": "string"
            }
          },
          {
            "description": "Only this key's requests. Requests refused before any work are left out, except spend_limit_reached, which stays with its key.",
            "in": "query",
            "name": "api_key_id",
            "schema": {
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "description": "latency_histogram: add each result's latency.histogram (null otherwise), to merge results yourself. Ask for it with the fewest groups you need: it adds up to 26 entries per result.",
            "in": "query",
            "name": "include",
            "schema": {
              "enum": [
                "latency_histogram"
              ],
              "type": "string"
            }
          },
          {
            "description": "Buckets per page (default and maximum: 31 daily or 168 hourly).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 168,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "ending_at": {
                            "description": "Bucket end, exclusive.",
                            "format": "date-time",
                            "type": "string"
                          },
                          "results": {
                            "description": "One entry per group (group_by); [] when the bucket had no requests.",
                            "items": {
                              "properties": {
                                "api_key_id": {
                                  "description": "Key ID; null unless grouped by api_key_id, and for requests refused before any work (a 402 or 429 with no charge, or while the API was paused), which count per account; spend_limit_reached keeps its key.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "cache_hits": {
                                  "description": "Successes served from the cache (free).",
                                  "type": "integer"
                                },
                                "credits_charged": {
                                  "description": "Credits charged.",
                                  "type": "integer"
                                },
                                "endpoint": {
                                  "description": "Endpoint ID; null unless grouped by endpoint, and for requests refused before any work (a 402 or 429 with no charge, or while the API was paused), which count per account.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "failed": {
                                  "description": "Requests answered with an error (free).",
                                  "type": "integer"
                                },
                                "latency": {
                                  "description": "How fast the successful requests were answered; null when none has a recorded latency (none succeeded, or all before 2026-10-31).",
                                  "properties": {
                                    "histogram": {
                                      "description": "The requests by bucket, fastest first, only buckets with requests. Add histograms bucket by bucket (by up_to_ms) to merge results, and read any percentile off the sum. null unless include=latency_histogram.",
                                      "items": {
                                        "properties": {
                                          "requests": {
                                            "description": "Requests in the bucket.",
                                            "type": "integer"
                                          },
                                          "up_to_ms": {
                                            "description": "The bucket's upper bound, inclusive, in milliseconds: it counts the requests that took at most this and more than the bound below. null for the bucket above the top bound.",
                                            "type": [
                                              "integer",
                                              "null"
                                            ]
                                          }
                                        },
                                        "required": [
                                          "up_to_ms",
                                          "requests"
                                        ],
                                        "type": "object"
                                      },
                                      "type": [
                                        "array",
                                        "null"
                                      ]
                                    },
                                    "p50_above_top": {
                                      "description": "true when the median is slower than the top bound: p50_ms is that bound and the true median is above it.",
                                      "type": "boolean"
                                    },
                                    "p50_ms": {
                                      "description": "Median time from receiving a request to answering it, in milliseconds, read off fixed buckets (upper bounds 25, 50, 100, 150, 200, 300, 400, 500, 750, 1000, 1250, 1500, 2000, 2500, 3000, 4000, 5000, 7500, 10000, 15000, 20000, 30000, 60000, 120000, 300000 ms): the upper bound of the bucket that holds the median request, so the true median is at most this and above the bound below it. When p50_above_top, the top bound.",
                                      "type": "integer"
                                    },
                                    "p95_above_top": {
                                      "description": "true when the 95th percentile is slower than the top bound: p95_ms is that bound and the true value is above it.",
                                      "type": "boolean"
                                    },
                                    "p95_ms": {
                                      "description": "95th percentile, read like p50_ms: 95% of the requests took at most this, to within one bucket. When p95_above_top, the top bound.",
                                      "type": "integer"
                                    },
                                    "requests": {
                                      "description": "Successful requests (outcome ok) with a recorded latency: what the percentiles describe. Failures are left out (many are answered at once, insufficient_credits or rate_limited, and would hide how fast data comes back).",
                                      "type": "integer"
                                    }
                                  },
                                  "required": [
                                    "requests",
                                    "p50_ms",
                                    "p95_ms",
                                    "p50_above_top",
                                    "p95_above_top",
                                    "histogram"
                                  ],
                                  "type": [
                                    "object",
                                    "null"
                                  ]
                                },
                                "requests": {
                                  "description": "Requests that reached an endpoint.",
                                  "type": "integer"
                                },
                                "status": {
                                  "description": "ok, or the error code the requests ended with; null unless grouped by status.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "succeeded": {
                                  "description": "Requests answered with data.",
                                  "type": "integer"
                                },
                                "surface": {
                                  "description": "How the requests reached the API: the surface of their request log entries (GET /v1/requests). null unless grouped by surface, and for requests made before surfaces were counted (2026-10-31).",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                }
                              },
                              "required": [
                                "endpoint",
                                "api_key_id",
                                "status",
                                "surface",
                                "requests",
                                "succeeded",
                                "failed",
                                "cache_hits",
                                "credits_charged",
                                "latency"
                              ],
                              "type": "object"
                            },
                            "type": "array"
                          },
                          "starting_at": {
                            "description": "Bucket start, inclusive (RFC 3339 UTC).",
                            "format": "date-time",
                            "type": "string"
                          }
                        },
                        "required": [
                          "starting_at",
                          "ending_at",
                          "results"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Usage report: requests and credits over time",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Usage report: requests and credits over time",
        "tags": [
          "Account"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/usage/rate": {
      "get": {
        "description": "How close the account runs to its runaway-protection ceiling (max_rps in GET /v1/account): per time bucket, the requests the ceiling counted, the busiest second (peak_rps), the average rate and the requests refused with rate_limited. The ceiling is a safety limit that stops a runaway client, not a plan limit: plans have no rate limit. Account-wide (every key and the dashboard). Buckets are listed oldest first, cursor-paged. Data is complete to within about 5 minutes. Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "usage.rate.list",
        "parameters": [
          {
            "description": "Start, inclusive: RFC 3339 or a date (UTC), rounded down to the bucket. Default: one full page of buckets before until.",
            "in": "query",
            "name": "since",
            "schema": {
              "maxLength": 40,
              "type": "string"
            }
          },
          {
            "description": "End, exclusive: RFC 3339 or a date (UTC). Default: now.",
            "in": "query",
            "name": "until",
            "schema": {
              "maxLength": 40,
              "type": "string"
            }
          },
          {
            "description": "Bucket size. Default 10m. At most 144 ten-minute, 168 hourly or 31 daily buckets per page.",
            "in": "query",
            "name": "bucket_width",
            "schema": {
              "enum": [
                "10m",
                "1h",
                "1d"
              ],
              "type": "string"
            }
          },
          {
            "description": "Buckets per page (default and maximum: 144 ten-minute, 168 hourly or 31 daily).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 168,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "average_rps": {
                            "description": "requests divided by the bucket's length in seconds (for the bucket now under way, by its seconds so far), to three significant figures.",
                            "type": "number"
                          },
                          "ending_at": {
                            "description": "Bucket end, exclusive.",
                            "format": "date-time",
                            "type": "string"
                          },
                          "peak_rps": {
                            "description": "The most requests counted in any one second of the bucket (a UTC clock second), refused ones included; 0 without requests. Compare it with max_rps (GET /v1/account).",
                            "type": "integer"
                          },
                          "rate_limited": {
                            "description": "Of requests, those refused with rate_limited (free) because the account was above its ceiling.",
                            "type": "integer"
                          },
                          "recorded": {
                            "description": "false for a bucket that ends before the account's request rate was first recorded (its first request since the rate has been measured): no data, rather than no requests. ",
                            "type": "boolean"
                          },
                          "requests": {
                            "description": "Requests the ceiling counted, refused ones included: endpoint requests (Prefer: respond-async ones too) and the gateway's own routes, from every key and the dashboard. Not counted: a job's items (the job paces them).",
                            "type": "integer"
                          },
                          "starting_at": {
                            "description": "Bucket start, inclusive (RFC 3339 UTC).",
                            "format": "date-time",
                            "type": "string"
                          }
                        },
                        "required": [
                          "starting_at",
                          "ending_at",
                          "requests",
                          "rate_limited",
                          "peak_rps",
                          "average_rps",
                          "recorded"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Request rate against the runaway-protection ceiling",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Request rate against the runaway-protection ceiling",
        "tags": [
          "Account"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "member",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/webhook_endpoints": {
      "get": {
        "description": "The account's webhook endpoints, newest first; never their secrets. Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "webhook_endpoints.list",
        "parameters": [
          {
            "description": "Endpoints per page (default and maximum 100).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page; omit to start from the newest.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "created_at": {
                            "format": "date-time",
                            "type": "string"
                          },
                          "created_by_user": {
                            "description": "The person (GET /v1/members user_id) who created this endpoint in the dashboard, or whose API key created it. They may have left the account since. Null when no person did, or it is from before this was recorded.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "disabled_reason": {
                            "description": "Why it is disabled: gone (it answered 410), failing (deliveries failed for 5 days), user. Null while enabled.",
                            "enum": [
                              "gone",
                              "failing",
                              "user"
                            ],
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "events": {
                            "description": "Event types it receives: types, prefix wildcards (job.*) or * for all.",
                            "items": {
                              "type": "string"
                            },
                            "type": "array"
                          },
                          "id": {
                            "description": "we_…",
                            "type": "string"
                          },
                          "object": {
                            "description": "Always webhook_endpoint.",
                            "enum": [
                              "webhook_endpoint"
                            ],
                            "type": "string"
                          },
                          "previous_secret_expires_at": {
                            "description": "Until then the previous secret signs too; null when none.",
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "secret": {
                            "description": "The signing secret (whsec_…): only in the create and rotate_secret answers. Store it.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "enum": [
                              "enabled",
                              "disabled"
                            ],
                            "type": "string"
                          },
                          "updated_at": {
                            "format": "date-time",
                            "type": "string"
                          },
                          "url": {
                            "description": "https URL deliveries are POSTed to. A key an agent collected from an approval reads only its host: https://host/.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "object",
                          "id",
                          "url",
                          "events",
                          "description",
                          "status",
                          "disabled_reason",
                          "previous_secret_expires_at",
                          "created_at",
                          "updated_at",
                          "created_by_user"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List webhook endpoints",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "List webhook endpoints",
        "tags": [
          "Webhooks"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "post": {
        "description": "Registers an https URL to receive the events it subscribes to, signed per Standard Webhooks. The answer is the only time `secret` is shown: store it to verify signatures. At most `max_endpoints` (16) per account and mode. Free.\n\n**Auth:** an API key with the `admin` scope, or the dashboard session.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "webhook_endpoints.create",
        "parameters": [
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "description": {
                    "maxLength": 500,
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "events": {
                    "description": "Event types, prefix wildcards (job.*) or *.",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 32,
                    "minItems": 1,
                    "type": "array"
                  },
                  "url": {
                    "description": "An https URL on a public host (no IP addresses of private, loopback or link-local networks; redirects are not followed).",
                    "maxLength": 2048,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "required": [
                  "url",
                  "events"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "created_at": {
                          "format": "date-time",
                          "type": "string"
                        },
                        "created_by_user": {
                          "description": "The person (GET /v1/members user_id) who created this endpoint in the dashboard, or whose API key created it. They may have left the account since. Null when no person did, or it is from before this was recorded.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "description": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "disabled_reason": {
                          "description": "Why it is disabled: gone (it answered 410), failing (deliveries failed for 5 days), user. Null while enabled.",
                          "enum": [
                            "gone",
                            "failing",
                            "user"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "events": {
                          "description": "Event types it receives: types, prefix wildcards (job.*) or * for all.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "id": {
                          "description": "we_…",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always webhook_endpoint.",
                          "enum": [
                            "webhook_endpoint"
                          ],
                          "type": "string"
                        },
                        "previous_secret_expires_at": {
                          "description": "Until then the previous secret signs too; null when none.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "secret": {
                          "description": "The signing secret (whsec_…): only in the create and rotate_secret answers. Store it.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "enum": [
                            "enabled",
                            "disabled"
                          ],
                          "type": "string"
                        },
                        "updated_at": {
                          "format": "date-time",
                          "type": "string"
                        },
                        "url": {
                          "description": "https URL deliveries are POSTed to. A key an agent collected from an approval reads only its host: https://host/.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "url",
                        "events",
                        "description",
                        "status",
                        "disabled_reason",
                        "previous_secret_expires_at",
                        "created_at",
                        "updated_at",
                        "created_by_user"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Register a webhook endpoint",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Register a webhook endpoint",
        "tags": [
          "Webhooks"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/webhook_endpoints/{id}": {
      "delete": {
        "description": "Deletes the endpoint; pending deliveries to it stop. Free.\n\n**Auth:** an API key with the `admin` scope, or the dashboard session.",
        "operationId": "webhook_endpoints.delete",
        "parameters": [
          {
            "description": "Webhook endpoint ID (we_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "deleted": {
                          "description": "Always true.",
                          "type": "boolean"
                        },
                        "id": {
                          "type": "string"
                        },
                        "object": {
                          "description": "The deleted object's type (webhook_endpoint).",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "deleted"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Delete a webhook endpoint",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Delete a webhook endpoint",
        "tags": [
          "Webhooks"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "get": {
        "description": "One webhook endpoint (never its secret). Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "webhook_endpoints.get",
        "parameters": [
          {
            "description": "Webhook endpoint ID (we_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "created_at": {
                          "format": "date-time",
                          "type": "string"
                        },
                        "created_by_user": {
                          "description": "The person (GET /v1/members user_id) who created this endpoint in the dashboard, or whose API key created it. They may have left the account since. Null when no person did, or it is from before this was recorded.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "description": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "disabled_reason": {
                          "description": "Why it is disabled: gone (it answered 410), failing (deliveries failed for 5 days), user. Null while enabled.",
                          "enum": [
                            "gone",
                            "failing",
                            "user"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "events": {
                          "description": "Event types it receives: types, prefix wildcards (job.*) or * for all.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "id": {
                          "description": "we_…",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always webhook_endpoint.",
                          "enum": [
                            "webhook_endpoint"
                          ],
                          "type": "string"
                        },
                        "previous_secret_expires_at": {
                          "description": "Until then the previous secret signs too; null when none.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "secret": {
                          "description": "The signing secret (whsec_…): only in the create and rotate_secret answers. Store it.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "enum": [
                            "enabled",
                            "disabled"
                          ],
                          "type": "string"
                        },
                        "updated_at": {
                          "format": "date-time",
                          "type": "string"
                        },
                        "url": {
                          "description": "https URL deliveries are POSTed to. A key an agent collected from an approval reads only its host: https://host/.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "url",
                        "events",
                        "description",
                        "status",
                        "disabled_reason",
                        "previous_secret_expires_at",
                        "created_at",
                        "updated_at",
                        "created_by_user"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get a webhook endpoint",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Get a webhook endpoint",
        "tags": [
          "Webhooks"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      },
      "patch": {
        "description": "Changes the URL, events, description or status; absent fields keep their value. Setting `status` to `enabled` re-enables an endpoint SocialTap disabled (see `disabled_reason`). Free.\n\n**Auth:** an API key with the `admin` scope, or the dashboard session.",
        "operationId": "webhook_endpoints.update",
        "parameters": [
          {
            "description": "Webhook endpoint ID (we_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "description": {
                    "maxLength": 500,
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "events": {
                    "items": {
                      "type": "string"
                    },
                    "type": [
                      "array",
                      "null"
                    ]
                  },
                  "status": {
                    "enum": [
                      "enabled",
                      "disabled"
                    ],
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "url": {
                    "maxLength": 2048,
                    "minLength": 1,
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "created_at": {
                          "format": "date-time",
                          "type": "string"
                        },
                        "created_by_user": {
                          "description": "The person (GET /v1/members user_id) who created this endpoint in the dashboard, or whose API key created it. They may have left the account since. Null when no person did, or it is from before this was recorded.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "description": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "disabled_reason": {
                          "description": "Why it is disabled: gone (it answered 410), failing (deliveries failed for 5 days), user. Null while enabled.",
                          "enum": [
                            "gone",
                            "failing",
                            "user"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "events": {
                          "description": "Event types it receives: types, prefix wildcards (job.*) or * for all.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "id": {
                          "description": "we_…",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always webhook_endpoint.",
                          "enum": [
                            "webhook_endpoint"
                          ],
                          "type": "string"
                        },
                        "previous_secret_expires_at": {
                          "description": "Until then the previous secret signs too; null when none.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "secret": {
                          "description": "The signing secret (whsec_…): only in the create and rotate_secret answers. Store it.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "enum": [
                            "enabled",
                            "disabled"
                          ],
                          "type": "string"
                        },
                        "updated_at": {
                          "format": "date-time",
                          "type": "string"
                        },
                        "url": {
                          "description": "https URL deliveries are POSTed to. A key an agent collected from an approval reads only its host: https://host/.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "url",
                        "events",
                        "description",
                        "status",
                        "disabled_reason",
                        "previous_secret_expires_at",
                        "created_at",
                        "updated_at",
                        "created_by_user"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Update a webhook endpoint",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Update a webhook endpoint",
        "tags": [
          "Webhooks"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": false,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/webhook_endpoints/{id}/deliveries": {
      "get": {
        "description": "Every delivery of an event to this endpoint, newest first: its last attempt's status code, duration and the start of the response body, and when the next attempt is due. Free.\n\n**Auth:** an API key with the `account:read` scope, or the dashboard session.",
        "operationId": "webhook_endpoints.deliveries.list",
        "parameters": [
          {
            "description": "Webhook endpoint ID (we_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Only deliveries in this status.",
            "in": "query",
            "name": "status",
            "schema": {
              "enum": [
                "pending",
                "succeeded",
                "failed"
              ],
              "type": "string"
            }
          },
          {
            "description": "Deliveries per page (default and maximum 100).",
            "in": "query",
            "name": "limit",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor of the previous page; omit to start from the newest.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "This page's items.",
                      "items": {
                        "properties": {
                          "attempts": {
                            "description": "Attempts made so far.",
                            "type": "integer"
                          },
                          "created_at": {
                            "format": "date-time",
                            "type": "string"
                          },
                          "delivered_at": {
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "duration_ms": {
                            "description": "The last attempt's duration.",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "error": {
                            "description": "Why the last attempt failed when there was no response.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "event_id": {
                            "type": "string"
                          },
                          "event_type": {
                            "type": "string"
                          },
                          "id": {
                            "description": "whd_…",
                            "type": "string"
                          },
                          "next_attempt_at": {
                            "format": "date-time",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "object": {
                            "description": "Always webhook_delivery.",
                            "enum": [
                              "webhook_delivery"
                            ],
                            "type": "string"
                          },
                          "response_excerpt": {
                            "description": "The start of the last response body.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "description": "pending: an attempt is due (next_attempt_at). failed: every attempt failed, or the endpoint was disabled or deleted.",
                            "enum": [
                              "pending",
                              "succeeded",
                              "failed"
                            ],
                            "type": "string"
                          },
                          "status_code": {
                            "description": "The last attempt's HTTP status; null when it got none (timeout, refused, blocked URL).",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "webhook_endpoint_id": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "object",
                          "id",
                          "event_id",
                          "event_type",
                          "webhook_endpoint_id",
                          "status",
                          "attempts",
                          "status_code",
                          "duration_ms",
                          "response_excerpt",
                          "error",
                          "created_at",
                          "delivered_at",
                          "next_attempt_at"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    },
                    "page": {
                      "properties": {
                        "end_reason": {
                          "description": "Why there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.",
                          "enum": [
                            "end",
                            "platform_limit",
                            "max_pages"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "description": "True when another page exists; then next_cursor is set. An empty page with has_more true is not the end.",
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass as cursor, with the same other parameters, to get the next page; null at the end.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next_cursor_expires_at": {
                          "description": "When next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "has_more",
                        "next_cursor",
                        "next_cursor_expires_at",
                        "end_reason"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "page",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List an endpoint's delivery attempts",
            "headers": {
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "List an endpoint's delivery attempts",
        "tags": [
          "Webhooks"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "account:read"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited"
          ]
        }
      }
    },
    "/v1/webhook_endpoints/{id}/rotate_secret": {
      "post": {
        "description": "Issues a new secret, shown once in the answer. The previous one keeps signing too (a second `v1,` signature) for `previous_secret_expires_in` seconds, so receivers can switch without dropping a delivery. Free.\n\n**Auth:** an API key with the `admin` scope, or the dashboard session.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "webhook_endpoints.rotate_secret",
        "parameters": [
          {
            "description": "Webhook endpoint ID (we_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "previous_secret_expires_in": {
                    "description": "Seconds the previous secret keeps signing (0 = stop now). Default: the maximum.",
                    "maximum": 86400,
                    "minimum": 0,
                    "type": [
                      "integer",
                      "null"
                    ]
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "created_at": {
                          "format": "date-time",
                          "type": "string"
                        },
                        "created_by_user": {
                          "description": "The person (GET /v1/members user_id) who created this endpoint in the dashboard, or whose API key created it. They may have left the account since. Null when no person did, or it is from before this was recorded.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "description": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "disabled_reason": {
                          "description": "Why it is disabled: gone (it answered 410), failing (deliveries failed for 5 days), user. Null while enabled.",
                          "enum": [
                            "gone",
                            "failing",
                            "user"
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "events": {
                          "description": "Event types it receives: types, prefix wildcards (job.*) or * for all.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "id": {
                          "description": "we_…",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always webhook_endpoint.",
                          "enum": [
                            "webhook_endpoint"
                          ],
                          "type": "string"
                        },
                        "previous_secret_expires_at": {
                          "description": "Until then the previous secret signs too; null when none.",
                          "format": "date-time",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "secret": {
                          "description": "The signing secret (whsec_…): only in the create and rotate_secret answers. Store it.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "enum": [
                            "enabled",
                            "disabled"
                          ],
                          "type": "string"
                        },
                        "updated_at": {
                          "format": "date-time",
                          "type": "string"
                        },
                        "url": {
                          "description": "https URL deliveries are POSTed to. A key an agent collected from an approval reads only its host: https://host/.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "url",
                        "events",
                        "description",
                        "status",
                        "disabled_reason",
                        "previous_secret_expires_at",
                        "created_at",
                        "updated_at",
                        "created_by_user"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Rotate a webhook endpoint's signing secret",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Rotate a webhook endpoint's signing secret",
        "tags": [
          "Webhooks"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/webhook_endpoints/{id}/test": {
      "post": {
        "description": "Emits a `webhook.test` event delivered to this endpoint only (signed and retried like any event). The answer is the event; its delivery appears in the endpoint's deliveries. Free.\n\n**Auth:** an API key with the `admin` scope, or the dashboard session.\n\nSend an `idempotency-key` header to retry safely: the same key and body within 1 day never repeat the work.",
        "operationId": "webhook_endpoints.test",
        "parameters": [
          {
            "description": "Webhook endpoint ID (we_…).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "On any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.",
            "in": "header",
            "name": "idempotency-key",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "data": {
                          "description": "The type's data object (small: a summary plus links)."
                        },
                        "id": {
                          "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                          "type": "string"
                        },
                        "object": {
                          "description": "Always event.",
                          "enum": [
                            "event"
                          ],
                          "type": "string"
                        },
                        "timestamp": {
                          "description": "When it happened.",
                          "format": "date-time",
                          "type": "string"
                        },
                        "type": {
                          "description": "The event type (event types table); new types may be added.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "type",
                        "timestamp",
                        "data"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "client_request_id": {
                          "description": "Your x-client-request-id, echoed; null when you sent none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits_charged": {
                          "description": "Always 0: the gateway's own routes are free (a job's items are charged as they end, at their endpoints' prices).",
                          "type": "integer"
                        },
                        "credits_remaining": {
                          "description": "Account balance; null without an account (signup) or when SocialTap could not read it.",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "request_id": {
                          "description": "Unique request ID; include it when contacting support.",
                          "type": "string"
                        },
                        "warnings": {
                          "description": "Things to act on that did not fail the request. [] when none.",
                          "items": {
                            "properties": {
                              "code": {
                                "description": "Machine-readable warning code (see the warnings list). New codes may be added.",
                                "type": "string"
                              },
                              "doc_url": {
                                "description": "Where to read more (the changelog entry, the endpoint's docs).",
                                "type": "string"
                              },
                              "fields": {
                                "description": "partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "message": {
                                "description": "What to do about it.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "doc_url"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "request_id",
                        "credits_charged",
                        "credits_remaining",
                        "client_request_id",
                        "warnings"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Send a webhook.test event to an endpoint",
            "headers": {
              "idempotent-replayed": {
                "$ref": "#/components/headers/idempotent-replayed"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_in_progress": {
                    "$ref": "#/components/examples/idempotency_key_in_progress"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_in_progress`: A request with this Idempotency-Key is still running. Retry after the seconds in the retry-after header to get that request's result.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_key_reused": {
                    "$ref": "#/components/examples/idempotency_key_reused"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`idempotency_key_reused`: This Idempotency-Key was already used for a different request (another route or body). Or it was used for this same request, which ran and returned a secret we no longer keep (details.reason answer_expired): running it again would create another. Use a new Idempotency-Key for a different request, and reuse a key only to retry the identical request. With reason answer_expired, check what the first request created (GET /v1/api_keys, GET /v1/webhook_endpoints) before sending it again under a new key.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "summary": "Send a webhook.test event to an endpoint",
        "tags": [
          "Webhooks"
        ],
        "x-socialtap-auth": {
          "auth": "key",
          "role": "admin",
          "scope": "admin"
        },
        "x-socialtap-pricing": {
          "max_credits": 0,
          "min_credits": 0,
          "prices": [],
          "unit": "request"
        },
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "idempotency_key_in_progress"
          ]
        }
      }
    },
    "/v1/x/community": {
      "get": {
        "description": "Returns a public X (formerly Twitter) Community from its link or ID: title, description, rules, admin and exact member count. It also has the topic, banner, creation time, NSFW flag, creator, moderator count, how people join (open, by approval or by invitation) and the question X asks them, who can invite, the words it is found by, and the few members X shows on its page.\n\nReturns `{data, meta}`: `data` is a `Community` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/x/community/ (Markdown: https://socialtap.dev/docs/reference/x/community/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/x/community/index.md)",
          "url": "https://socialtap.dev/docs/reference/x/community/"
        },
        "operationId": "x.community.get",
        "parameters": [
          {
            "description": "The community: its link on x.com or twitter.com (x.com/i/communities/<id>, any of its views such as /about, /media or /members included, mobile hosts and any query too) or its numeric ID.",
            "example": "https://x.com/i/communities/1493446837214187523",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "The community: its link on x.com or twitter.com (x.com/i/communities/<id>, any of its views such as /about, /media or /members included, mobile hosts and any query too) or its numeric ID.",
              "examples": [
                "https://x.com/i/communities/1493446837214187523"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": null,
                        "banner_url": "https://pbs.twimg.com/community_banner_img/1915033378811772928/KdaKUaRP?format=png&name=orig",
                        "categories": [
                          "Entrepreneurship"
                        ],
                        "created_at": "2022-02-15T04:47:27Z",
                        "description": "Share what you're working on. Get feedback. Help each other move forward. – Sponsored by bolt.new ⚡",
                        "id": "1493446837214187523",
                        "is_nsfw": false,
                        "metrics": {
                          "member_count": 270227
                        },
                        "moderators": [
                          {
                            "avatar_url": "https://pbs.twimg.com/profile_images/1857124042433572864/iMivVaYP.jpg",
                            "display_name": "Marc Köhlbrugge",
                            "id": "641633",
                            "is_verified": true,
                            "url": "https://x.com/marckohlbrugge",
                            "username": "marckohlbrugge"
                          }
                        ],
                        "name": null,
                        "platform": "x",
                        "platform_specific": {
                          "x": {
                            "creator": {
                              "avatar_url": "https://pbs.twimg.com/profile_images/1857124042433572864/iMivVaYP.jpg",
                              "display_name": "Marc Köhlbrugge",
                              "id": "641633",
                              "is_verified": true,
                              "url": "https://x.com/marckohlbrugge",
                              "username": "marckohlbrugge"
                            },
                            "invite_policy": "members",
                            "join_policy": "open",
                            "join_question": "What are you working on?",
                            "moderator_count": 6,
                            "sample_members": [
                              {
                                "avatar_url": "https://pbs.twimg.com/profile_images/1857124042433572864/iMivVaYP.jpg",
                                "display_name": "Marc Köhlbrugge",
                                "id": "641633",
                                "is_verified": true,
                                "url": "https://x.com/marckohlbrugge",
                                "username": "marckohlbrugge"
                              },
                              {
                                "avatar_url": "https://pbs.twimg.com/profile_images/1142795908221952001/QdBqHhdn.jpg",
                                "display_name": "🚧 WIP",
                                "id": "11212692",
                                "is_verified": false,
                                "url": "https://x.com/wip",
                                "username": "wip"
                              },
                              {
                                "avatar_url": "https://pbs.twimg.com/profile_images/1416201794200477700/Kasb_zJv.jpg",
                                "display_name": "Build in Public",
                                "id": "2729705040",
                                "is_verified": true,
                                "url": "https://x.com/buildinpublic",
                                "username": "buildinpublic"
                              }
                            ],
                            "search_tags": [
                              "buildinpublic",
                              "buildinginpublic",
                              "builtinpublic"
                            ]
                          }
                        },
                        "privacy": "public",
                        "rules": [
                          {
                            "description": "Don't be scared to share unfinished work",
                            "title": "Share what you're working on"
                          },
                          {
                            "description": "Visual tweets tend to grab people's attention",
                            "title": "Screenshots, screencasts, drafts, etc"
                          },
                          {
                            "description": "Don't ask for upvotes or advertise your products/services.",
                            "title": "No self-promotion"
                          }
                        ],
                        "title": "Build in Public",
                        "unknown_fields": [],
                        "url": "https://x.com/i/communities/1493446837214187523"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "x",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 325,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "community",
                          "id": "1493446837214187523",
                          "url": "https://x.com/i/communities/1493446837214187523"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/XCommunityResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Rules, admin and exact member count",
        "tags": [
          "X"
        ],
        "x-socialtap-endpoint": "x.community",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "community",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/x/post": {
      "get": {
        "description": "Returns a public X (formerly Twitter) post from its link or ID: full text, author, media, and exact view, like, repost, reply and bookmark counts. Long posts and X Articles come whole. It also has the quote count, the post it quotes or replies to with its own text and counts, its poll with exact votes, link card, hashtags, mentions, cashtags, community and edit history.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/x/post/ (Markdown: https://socialtap.dev/docs/reference/x/post/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/x/post/index.md)",
          "url": "https://socialtap.dev/docs/reference/x/post/"
        },
        "operationId": "x.post.get",
        "parameters": [
          {
            "description": "X post: a link (x.com or twitter.com, /<username>/status/<id> with or without a view such as /photo/1 or a query such as ?s=20, /i/web/status/<id>, /i/status/<id>, /<username>/article/<id>, old /statuses/ and #! links, mobile.twitter.com) or a bare numeric post ID.",
            "example": "https://x.com/NASA/status/2117633046002225363",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "X post: a link (x.com or twitter.com, /<username>/status/<id> with or without a view such as /photo/1 or a query such as ?s=20, /i/web/status/<id>, /i/status/<id>, /<username>/article/<id>, old /statuses/ and #! links, mobile.twitter.com) or a bare numeric post ID.",
              "examples": [
                "https://x.com/NASA/status/2117633046002225363"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "author": {
                          "avatar_url": "https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB.jpg",
                          "display_name": "NASA",
                          "id": "11348282",
                          "is_verified": true,
                          "url": "https://x.com/NASA",
                          "username": "NASA"
                        },
                        "coauthors": [],
                        "duration_ms": null,
                        "hashtags": [],
                        "id": "2117633046002225363",
                        "is_nsfw": false,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": "en",
                        "media": [
                          {
                            "alt_text": "An intricate cloud of white dust takes center stage in this photo, rising in a windy pillar. The background features rust-colored dust with dots of distant stars and galaxies shining through.",
                            "duration_ms": null,
                            "expires_at": null,
                            "height": 1385,
                            "thumbnail_url": null,
                            "type": "image",
                            "url": "https://pbs.twimg.com/media/HWNYCEHWsAAO3PW.jpg?name=orig",
                            "width": 2000
                          }
                        ],
                        "mentions": [
                          "NASAWebb"
                        ],
                        "metrics": {
                          "comment_count": 181,
                          "like_count": 2300,
                          "quote_count": 42,
                          "repost_count": 315,
                          "save_count": 120,
                          "share_count": null,
                          "view_count": 490407
                        },
                        "platform": "x",
                        "platform_specific": {
                          "x": {
                            "article": null,
                            "author_metrics": {
                              "follower_count": 92294019,
                              "following_count": 115,
                              "post_count": 74490,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "author_verified_type": "government",
                            "card": null,
                            "cashtags": [],
                            "community": null,
                            "conversation_id": "2117633046002225363",
                            "edit_post_ids": [
                              "2117633046002225363"
                            ],
                            "is_author_blue_verified": true,
                            "is_edited": false,
                            "links": [],
                            "media_variants": [],
                            "poll": null,
                            "quoted_post": null,
                            "quoted_post_id": null,
                            "reply_to_author": null,
                            "reply_to_post_id": null,
                            "reposted_post": null,
                            "reposted_post_id": null,
                            "source": null
                          }
                        },
                        "platform_type": "post",
                        "published_at": "2026-11-03T15:00:36Z",
                        "text": "This smoky specter is the Cat’s Head Nebula, captured in intricate detail by @NASAWebb. Its name comes from its shape, which resembles a cosmic kitty sitting with its back toward the viewer. What do you see?",
                        "thumbnail_url": "https://pbs.twimg.com/media/HWNYCEHWsAAO3PW.jpg?name=orig",
                        "title": null,
                        "type": "image",
                        "unknown_fields": [],
                        "url": "https://x.com/NASA/status/2117633046002225363"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "x",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 272,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "post",
                          "id": "2117633046002225363",
                          "url": "https://x.com/NASA/status/2117633046002225363"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/XPostResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Full text, media and exact view counts",
        "tags": [
          "X"
        ],
        "x-socialtap-endpoint": "x.post",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/x/profile": {
      "get": {
        "description": "Returns a public X (formerly Twitter) profile from a username, link or ID: exact follower, following and post counts, bio, links and verification. It also has the website, location, join date, full-size profile picture and header, which check the account has (blue, business or government), its affiliate badge and professional category, whether its posts are protected, its pinned posts, and X's counts of the account's media, likes and lists.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/x/profile/ (Markdown: https://socialtap.dev/docs/reference/x/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/x/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/x/profile/"
        },
        "operationId": "x.profile.get",
        "parameters": [
          {
            "description": "X account: a username with or without the @ (NASA, @NASA), a numeric user ID (11348282), or a profile link (x.com/NASA or twitter.com/NASA, with or without a tab such as /media or /with_replies, mobile.twitter.com, x.com/i/user/11348282, a Follow-button or intent link such as x.com/intent/user?screen_name=NASA or ?user_id=11348282, with any query such as ?s=20). Usernames are case-insensitive. A bare number is a user ID; a number no account has as its ID is looked up as a username, and @ before digits (@123) always means the username.",
            "example": "NASA",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "X account: a username with or without the @ (NASA, @NASA), a numeric user ID (11348282), or a profile link (x.com/NASA or twitter.com/NASA, with or without a tab such as /media or /with_replies, mobile.twitter.com, x.com/i/user/11348282, a Follow-button or intent link such as x.com/intent/user?screen_name=NASA or ?user_id=11348282, with any query such as ?s=20). Usernames are case-insensitive. A bare number is a user ID; a number no account has as its ID is looked up as a username, and @ before digits (@123) always means the username.",
              "examples": [
                "NASA"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "avatar_url": "https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB.jpg",
                        "banner_url": "https://pbs.twimg.com/profile_banners/11348282/1788992290",
                        "bio": "Making the seemingly impossible, possible. ✨",
                        "category": null,
                        "country_code": null,
                        "created_at": "2007-12-19T20:20:32Z",
                        "display_name": "NASA",
                        "external_links": [
                          {
                            "title": "nasa.gov",
                            "url": "http://www.nasa.gov/"
                          }
                        ],
                        "id": "11348282",
                        "is_private": false,
                        "is_verified": true,
                        "location": "Pale Blue Dot",
                        "metrics": {
                          "follower_count": 92293807,
                          "following_count": 115,
                          "post_count": 74490,
                          "total_like_count": null,
                          "total_view_count": null
                        },
                        "platform": "x",
                        "platform_specific": {
                          "x": {
                            "affiliation": null,
                            "highlighted_post_count": 289,
                            "is_blue_verified": true,
                            "is_identity_verified": false,
                            "is_possibly_sensitive": false,
                            "like_count": 17060,
                            "listed_count": 96858,
                            "media_count": 28224,
                            "pinned_post_ids": [],
                            "professional_type": null,
                            "verified_at": "2009-08-07T19:53:50Z",
                            "verified_type": "government",
                            "withheld_in_countries": []
                          }
                        },
                        "type": "organization",
                        "unknown_fields": [],
                        "url": "https://x.com/NASA",
                        "username": "NASA"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "x",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 244,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "11348282",
                          "url": "https://x.com/NASA"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/XProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Exact follower counts, bio and verification",
        "tags": [
          "X"
        ],
        "x-socialtap-endpoint": "x.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/x/search_communities": {
      "get": {
        "description": "Returns the X (Twitter) Communities a web search finds for a topic, niche or name: each one's link, plus its title and description where indexed. Add fill=true to get each community's full record from X in the same response: ID, exact member count, rules, topic, banner, admin, NSFW flag and how people join. Page through results with the cursor.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/x/search_communities/ (Markdown: https://socialtap.dev/docs/reference/x/search_communities/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/x/search_communities/index.md)",
          "url": "https://socialtap.dev/docs/reference/x/search_communities/"
        },
        "operationId": "x.search_communities.list",
        "parameters": [
          {
            "description": "Words to find X Communities by, as a web search reads them: a topic, a niche, a community's name (machine learning, build in public, \"indie hackers\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint.",
            "example": "build in public",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find X Communities by, as a web search reads them: a topic, a niche, a community's name (machine learning, build in public, \"indie hackers\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint.",
              "examples": [
                "build in public"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "community.title"
                          ],
                          "community": {
                            "avatar_url": null,
                            "description": null,
                            "id": null,
                            "metrics": {
                              "member_count": null
                            },
                            "name": null,
                            "privacy": null,
                            "title": "Build in Public",
                            "url": "https://x.com/i/communities/1493446837214187523"
                          },
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://x.com/i/communities/1493446837214187523",
                          "place": null,
                          "platform": "x",
                          "platform_specific": {},
                          "position": 0,
                          "post": null,
                          "profile": null,
                          "snippet": "My goal for buildinpublic.com is to become the definitive database of all makers and their projects To that end, you can now add your projects to buildinpublic.com To verify ownership and get the verified checkmark, just add the <meta name=\"twitter:creator\" Show more",
                          "sound": null,
                          "title": "Build in Public Community / X",
                          "type": "community",
                          "unknown_fields": [],
                          "url": "https://x.com/i/communities/1493446837214187523"
                        },
                        {
                          "approximate_fields": [
                            "community.description",
                            "community.metrics.member_count",
                            "community.title"
                          ],
                          "community": {
                            "avatar_url": null,
                            "description": "Here is a open community for Indie hackers and SaaS Founders who are building in public, come and share your daily journey.",
                            "id": null,
                            "metrics": {
                              "member_count": 392
                            },
                            "name": null,
                            "privacy": null,
                            "title": "Build In Public - SaaS",
                            "url": "https://x.com/i/communities/1828843041869713562"
                          },
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://x.com/i/communities/1828843041869713562",
                          "place": null,
                          "platform": "x",
                          "platform_specific": {},
                          "position": 1,
                          "post": null,
                          "profile": null,
                          "snippet": "Here is a open community for Indie hackers and SaaS Founders who are building in public, come and share your daily journey.",
                          "sound": null,
                          "title": "Build In Public - SaaS Community on X - 392 Members",
                          "type": "community",
                          "unknown_fields": [],
                          "url": "https://x.com/i/communities/1828843041869713562"
                        },
                        {
                          "approximate_fields": [
                            "community.description",
                            "community.title"
                          ],
                          "community": {
                            "avatar_url": null,
                            "description": "The community for @BuildinPublic__ Bootstrappers, No Code/Low Code, and for Founders to share their builds & experiences 🚀",
                            "id": null,
                            "metrics": {
                              "member_count": null
                            },
                            "name": null,
                            "privacy": null,
                            "title": "BuildinPublic",
                            "url": "https://x.com/i/communities/1495042358068477955"
                          },
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://x.com/i/communities/1495042358068477955",
                          "place": null,
                          "platform": "x",
                          "platform_specific": {},
                          "position": 2,
                          "post": null,
                          "profile": null,
                          "snippet": "The community for @BuildinPublic__ Bootstrappers, No Code/Low Code, and for Founders to share their builds & experiences 🚀",
                          "sound": null,
                          "title": "BuildinPublic on X",
                          "type": "community",
                          "unknown_fields": [],
                          "url": "https://x.com/i/communities/1495042358068477955"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "x",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1139,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/XSearch_communitiesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Communities by topic, niche or name",
        "tags": [
          "X"
        ],
        "x-socialtap-endpoint": "x.search_communities",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/x/search_hashtags": {
      "get": {
        "description": "Returns the X (Twitter) hashtags a web search finds for a keyword or topic, each with its name as X spells it and its link. Use it to discover a topic's hashtags and their variants, then the X (Twitter) Post Search API for the posts that carry one. Page through results with the cursor.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/x/search_hashtags/ (Markdown: https://socialtap.dev/docs/reference/x/search_hashtags/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/x/search_hashtags/index.md)",
          "url": "https://socialtap.dev/docs/reference/x/search_hashtags/"
        },
        "operationId": "x.search_hashtags.list",
        "parameters": [
          {
            "description": "Words to find X hashtags by, as a web search reads them: a topic, a niche, a name (cooking, bitcoin, \"machine learning\", 料理). A leading # is dropped, quotes keep a phrase together and a leading - leaves a word out.",
            "example": "cooking",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find X hashtags by, as a web search reads them: a topic, a niche, a name (cooking, bitcoin, \"machine learning\", 料理). A leading # is dropped, quotes keep a phrase together and a leading - leaves a word out.",
              "examples": [
                "cooking"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": {
                            "description": null,
                            "id": null,
                            "metrics": {
                              "post_count": null
                            },
                            "name": "cooking",
                            "thumbnail_url": null,
                            "url": "https://x.com/hashtag/cooking"
                          },
                          "matched_url": "https://x.com/hashtag/cooking?f=live",
                          "place": null,
                          "platform": "x",
                          "platform_specific": {},
                          "position": 0,
                          "post": null,
                          "profile": null,
                          "snippet": "We’ve detected that JavaScript is disabled in this browser. Please enable JavaScript or switch to a supported browser to continue using x.com. You can see a list of supported browsers in our Help Center · Условия за ползване Политика за поверителност ...",
                          "sound": null,
                          "title": "\"#cooking\" - Results on X | Live Posts & Updates",
                          "type": "hashtag",
                          "unknown_fields": [],
                          "url": "https://x.com/hashtag/cooking"
                        },
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": {
                            "description": null,
                            "id": null,
                            "metrics": {
                              "post_count": null
                            },
                            "name": "Cooking_illife",
                            "thumbnail_url": null,
                            "url": "https://x.com/hashtag/cooking_illife"
                          },
                          "matched_url": "https://x.com/hashtag/Cooking_illife",
                          "place": null,
                          "platform": "x",
                          "platform_specific": {},
                          "position": 1,
                          "post": null,
                          "profile": null,
                          "snippet": "From breaking news and entertainment to sports and politics, get the full story with all the live commentary.",
                          "sound": null,
                          "title": "\"#Cooking_illife\" - Results on X | Live Posts & Updates",
                          "type": "hashtag",
                          "unknown_fields": [],
                          "url": "https://x.com/hashtag/cooking_illife"
                        },
                        {
                          "approximate_fields": [],
                          "community": null,
                          "details": null,
                          "hashtag": {
                            "description": null,
                            "id": null,
                            "metrics": {
                              "post_count": null
                            },
                            "name": "mylovecooking",
                            "thumbnail_url": null,
                            "url": "https://x.com/hashtag/mylovecooking"
                          },
                          "matched_url": "https://x.com/hashtag/mylovecooking",
                          "place": null,
                          "platform": "x",
                          "platform_specific": {},
                          "position": 2,
                          "post": null,
                          "profile": null,
                          "snippet": "From breaking news and entertainment to sports and politics, get the full story with all the live commentary.",
                          "sound": null,
                          "title": "\"#mylovecooking\" - Results on X | Live Posts & Updates",
                          "type": "hashtag",
                          "unknown_fields": [],
                          "url": "https://x.com/hashtag/mylovecooking"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "x",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1033,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/XSearch_hashtagsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Hashtags related to a keyword or topic",
        "tags": [
          "X"
        ],
        "x-socialtap-endpoint": "x.search_hashtags",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/x/search_posts": {
      "get": {
        "description": "Returns the X (Twitter) posts a web search finds for your words, a #hashtag or an @handle, each with its link, author and exact publish time. The text and the author's name are the search index's copy. Add fill=true to get each post's full record from X in the same response: full text, media, views, likes, reposts, replies and the author's verification. Filter by date with since and until, and page through results with the cursor.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/x/search_posts/ (Markdown: https://socialtap.dev/docs/reference/x/search_posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/x/search_posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/x/search_posts/"
        },
        "operationId": "x.search_posts.list",
        "parameters": [
          {
            "description": "Words to find X posts by, as a web search reads them: a topic, a product, a phrase (coffee roaster, \"blue bottle\" review), or one #hashtag or @handle to find posts that show it. Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint. X's since: and until: operators are read as the since and until params; its other operators (from:, to:, lang:, min_faves:, min_retweets:, min_replies:, filter:, include:, exclude: and the like) can't be applied to a web search and are refused.",
            "example": "coffee roaster",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find X posts by, as a web search reads them: a topic, a product, a phrase (coffee roaster, \"blue bottle\" review), or one #hashtag or @handle to find posts that show it. Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint. X's since: and until: operators are read as the since and until params; its other operators (from:, to:, lang:, min_faves:, min_retweets:, min_replies:, filter:, include:, exclude: and the like) can't be applied to a web search and are refused.",
              "examples": [
                "coffee roaster"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. By the post's exact time, read from its ID; the search engine is asked for the same dates, so this also finds recent posts the plain ranking leaves out. A date filter narrows a ranking, not an order: results are still by relevance.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. By the post's exact time, read from its ID; the search engine is asked for the same dates, so this also finds recent posts the plain ranking leaves out. A date filter narrows a ranking, not an order: results are still by relevance.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). By the post's exact time, read from its ID.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). By the post's exact time, read from its ID.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "post.author.display_name"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://x.com/StPeteRising/status/1765465672597774460",
                          "place": null,
                          "platform": "x",
                          "platform_specific": {},
                          "position": 0,
                          "post": {
                            "author": {
                              "avatar_url": null,
                              "display_name": "St. Pete Rising",
                              "id": null,
                              "is_verified": null,
                              "url": "https://x.com/StPeteRising",
                              "username": "StPeteRising"
                            },
                            "id": "1765465672597774460",
                            "metrics": {
                              "comment_count": null,
                              "like_count": null,
                              "quote_count": null,
                              "repost_count": null,
                              "save_count": null,
                              "share_count": null,
                              "view_count": null
                            },
                            "published_at": "2024-03-06T19:53:11Z",
                            "text": null,
                            "thumbnail_url": null,
                            "title": null,
                            "url": "https://x.com/StPeteRising/status/1765465672597774460"
                          },
                          "profile": null,
                          "snippet": "A new coffee roaster that focuses on specialty coffees is up and running at 1920 ½ 1st Avenue South , behind Spitfire Comedy House, in St. Petersburg’s Grand Central District.",
                          "sound": null,
                          "title": "St. Pete Rising (@StPeteRising) on X",
                          "type": "post",
                          "unknown_fields": [],
                          "url": "https://x.com/StPeteRising/status/1765465672597774460"
                        },
                        {
                          "approximate_fields": [
                            "post.author.display_name",
                            "post.text"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://x.com/nimbusroasters/status/1326892799434821634",
                          "place": null,
                          "platform": "x",
                          "platform_specific": {},
                          "position": 1,
                          "post": {
                            "author": {
                              "avatar_url": null,
                              "display_name": "Nimbus Roasters",
                              "id": null,
                              "is_verified": null,
                              "url": "https://x.com/nimbusroasters",
                              "username": "nimbusroasters"
                            },
                            "id": "1326892799434821634",
                            "metrics": {
                              "comment_count": null,
                              "like_count": null,
                              "quote_count": null,
                              "repost_count": null,
                              "save_count": null,
                              "share_count": null,
                              "view_count": null
                            },
                            "published_at": "2020-11-12T14:21:10Z",
                            "text": "Fresh locally roasted coffee + free delivery ...",
                            "thumbnail_url": null,
                            "title": null,
                            "url": "https://x.com/nimbusroasters/status/1326892799434821634"
                          },
                          "profile": null,
                          "snippet": "We are an independent, specialty coffee roaster dedicated to the craft of curating a unique coffee experience.",
                          "sound": null,
                          "title": "Nimbus Roasters on X: \"Fresh locally roasted coffee + free delivery ...",
                          "type": "post",
                          "unknown_fields": [],
                          "url": "https://x.com/nimbusroasters/status/1326892799434821634"
                        },
                        {
                          "approximate_fields": [
                            "post.author.display_name",
                            "post.text"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://x.com/TODDCastPodcast/status/2117307249693536434",
                          "place": null,
                          "platform": "x",
                          "platform_specific": {},
                          "position": 2,
                          "post": {
                            "author": {
                              "avatar_url": null,
                              "display_name": "Todd Hancock",
                              "id": null,
                              "is_verified": null,
                              "url": "https://x.com/TODDCastPodcast",
                              "username": "TODDCastPodcast"
                            },
                            "id": "2117307249693536434",
                            "metrics": {
                              "comment_count": null,
                              "like_count": null,
                              "quote_count": null,
                              "repost_count": null,
                              "save_count": null,
                              "share_count": null,
                              "view_count": null
                            },
                            "published_at": "2026-11-02T17:26:00Z",
                            "text": "☕ Why settle for average coffee? @Milano...",
                            "thumbnail_url": null,
                            "title": null,
                            "url": "https://x.com/TODDCastPodcast/status/2117307249693536434"
                          },
                          "profile": null,
                          "snippet": "Milano Coffee Roasters is a Vancouver based artisan roastery with legacy and tradition dating back three generations of Italian Coffee Heritage blended with over thirty years of West Coast Culture.",
                          "sound": null,
                          "title": "Todd Hancock on X: \"☕ Why settle for average coffee? @Milano...",
                          "type": "post",
                          "unknown_fields": [],
                          "url": "https://x.com/TODDCastPodcast/status/2117307249693536434"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "x",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1265,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/XSearch_postsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Posts by keyword, hashtag or @mention",
        "tags": [
          "X"
        ],
        "x-socialtap-endpoint": "x.search_posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/x/search_profiles": {
      "get": {
        "description": "Returns the X (Twitter) accounts a web search finds for a name, keyword, niche or place, each with its username and profile link. Display name, bio and counts come from the search index where it shows them. Add fill=true to get each account's full profile from X in the same response: user ID, exact counts, verification, avatar and links. Page through results with the cursor.\n\nReturns `{data, page, meta}`: `data` holds up to 50 `Web result` items (the shared schema, the same on every platform), the search engine's ranking (most relevant first). For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit + 1 per result filled in per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/x/search_profiles/ (Markdown: https://socialtap.dev/docs/reference/x/search_profiles/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/x/search_profiles/index.md)",
          "url": "https://socialtap.dev/docs/reference/x/search_profiles/"
        },
        "operationId": "x.search_profiles.list",
        "parameters": [
          {
            "description": "Words to find X accounts by, as a web search reads them: a name, a niche, a business type, a place (sam altman, coffee roaster, yoga studio austin, \"blue bottle\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint.",
            "example": "coffee roaster",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Words to find X accounts by, as a web search reads them: a name, a niche, a business type, a place (sam altman, coffee roaster, yoga studio austin, \"blue bottle\"). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint.",
              "examples": [
                "coffee roaster"
              ],
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
            "example": "true",
            "in": "query",
            "name": "fill",
            "schema": {
              "description": "true also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.",
              "enum": [
                "true",
                "false"
              ],
              "examples": [
                "true"
              ],
              "type": "string"
            }
          },
          {
            "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
            "example": "BR",
            "in": "query",
            "name": "country",
            "schema": {
              "description": "Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.",
              "examples": [
                "BR"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 50,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "profile.bio",
                            "profile.display_name"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://x.com/swroasting",
                          "place": null,
                          "platform": "x",
                          "platform_specific": {},
                          "position": 0,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "Artisan coffee roasters specializing in single origin coffees.",
                            "display_name": "S&W Craft Roasting",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": null,
                              "following_count": null,
                              "post_count": null,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://x.com/swroasting",
                            "username": "swroasting"
                          },
                          "snippet": "Artisan coffee roasters specializing in single origin coffees.",
                          "sound": null,
                          "title": "S&W Craft Roasting (@swroasting) on X",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://x.com/swroasting"
                        },
                        {
                          "approximate_fields": [
                            "profile.bio",
                            "profile.display_name"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://x.com/CoRoLNK",
                          "place": null,
                          "platform": "x",
                          "platform_specific": {},
                          "position": 1,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "Specialty-grade coffee, roasted fresh in small batches by The Coffee Roaster with 30 years of experience.",
                            "display_name": "The Coffee Roaster",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": null,
                              "following_count": null,
                              "post_count": null,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://x.com/CoRoLNK",
                            "username": "CoRoLNK"
                          },
                          "snippet": "Specialty-grade coffee, roasted fresh in small batches by The Coffee Roaster with 30 years of experience.",
                          "sound": null,
                          "title": "The Coffee Roaster (@CoRoLNK) on X",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://x.com/CoRoLNK"
                        },
                        {
                          "approximate_fields": [
                            "profile.bio",
                            "profile.display_name"
                          ],
                          "community": null,
                          "details": null,
                          "hashtag": null,
                          "matched_url": "https://x.com/roastmasters",
                          "place": null,
                          "platform": "x",
                          "platform_specific": {},
                          "position": 2,
                          "post": null,
                          "profile": {
                            "avatar_url": null,
                            "bio": "Everything for the home coffee roaster: coffee roasters, unroasted green coffee, equipment. Also, major Technivorm coffeemaker distributor. All the best.",
                            "display_name": "Roastmasters.com",
                            "id": null,
                            "is_verified": null,
                            "metrics": {
                              "follower_count": null,
                              "following_count": null,
                              "post_count": null,
                              "total_like_count": null,
                              "total_view_count": null
                            },
                            "url": "https://x.com/roastmasters",
                            "username": "roastmasters"
                          },
                          "snippet": "Everything for the home coffee roaster: coffee roasters, unroasted green coffee, equipment. Also, major Technivorm coffeemaker distributor. All the best.",
                          "sound": null,
                          "title": "Roastmasters.com (@roastmasters) on X",
                          "type": "profile",
                          "unknown_fields": [],
                          "url": "https://x.com/roastmasters"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "x",
                        "source": "web_search",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1243,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": null,
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/XSearch_profilesResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Accounts by name, keyword, niche or place",
        "tags": [
          "X"
        ],
        "x-socialtap-endpoint": "x.search_profiles",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 86400,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "the search engine's ranking (most relevant first)",
          "page_max": 50,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 51,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit + 1 per result filled in",
              "max": 51,
              "per": 1,
              "source": "",
              "unit": "filled_result",
              "unit_max": 50
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "web_result",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/youtube/comments": {
      "get": {
        "description": "Returns the public top-level comments of a YouTube video, short or live replay, a page at a time, newest first or by YouTube's Top ranking. Each comment has its text, author handle and channel, posting time, likes, reply count, and whether it is pinned, hearted, edited or written by the creator. Newest first also takes since and until. Accepts any YouTube video link or an 11-character video ID.\n\nReturns `{data, page, meta}`: `data` holds up to 20 `Comment` items (the shared schema, the same on every platform), newest first with sort=newest (the default), YouTube's Top comments ranking with sort=popular. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/youtube/comments/ (Markdown: https://socialtap.dev/docs/reference/youtube/comments/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/youtube/comments/index.md)",
          "url": "https://socialtap.dev/docs/reference/youtube/comments/"
        },
        "operationId": "youtube.comments.list",
        "parameters": [
          {
            "description": "YouTube video URL (watch, youtu.be, shorts, live, embed, m./music. hosts) or an 11-character video ID.",
            "example": "jNQXAC9IVRw",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "YouTube video URL (watch, youtu.be, shorts, live, embed, m./music. hosts) or an 11-character video ID.",
              "examples": [
                "https://www.youtube.com/watch?v=jNQXAC9IVRw"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Order of the results. newest (default): newest first. popular: YouTube's Top comments ranking. Either way the video's pinned comment comes first.",
            "example": "newest",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "newest",
              "description": "Order of the results. newest (default): newest first. popular: YouTube's Top comments ranking. Either way the video's pinned comment comes first.",
              "enum": [
                "newest",
                "popular"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at, which YouTube only shows as a relative label (\"2 days ago\"): the walk stops at the first comment whose label is older, so comments up to one label unit older can be included.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Compared with published_at, which YouTube only shows as a relative label (\"2 days ago\"): the walk stops at the first comment whose label is older, so comments up to one label unit older can be included.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC).",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 20,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [
                            "published_at",
                            "metrics.like_count",
                            "metrics.reply_count"
                          ],
                          "author": {
                            "avatar_url": "https://yt3.ggpht.com/i8RqA9tYqbbnOi4mlnYEY7IR3kXAoDqQbM_5Sfzw7OjTubiGsOaTdlrIZmj-I0q0Vup68eqs=s88-c-k-c0x00ffffff-no-rj",
                            "display_name": null,
                            "id": "UCC5NfQ6Mf0dq_eEwv4P_hWA",
                            "is_verified": true,
                            "url": "https://www.youtube.com/channel/UCC5NfQ6Mf0dq_eEwv4P_hWA",
                            "username": "SanDiegoZoo"
                          },
                          "edited_at": null,
                          "id": "UgzuC3zzpRZkjc5Qzsd4AaABAg",
                          "is_by_post_author": false,
                          "is_edited": false,
                          "is_liked_by_author": true,
                          "is_pinned": true,
                          "metrics": {
                            "like_count": 4800000,
                            "reply_count": 1000
                          },
                          "parent_id": null,
                          "platform": "youtube",
                          "platform_specific": {},
                          "post_id": "jNQXAC9IVRw",
                          "published_at": "2020-10-26T18:59:19Z",
                          "text": "We're so honored that the first ever YouTube video was filmed here!",
                          "unknown_fields": [],
                          "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw&lc=UgzuC3zzpRZkjc5Qzsd4AaABAg"
                        },
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": "https://yt3.ggpht.com/U9zdJRwdpo6WwsenxMf6AyMyRMBTWoKsyAWCnJXdbPbNKh-YNEWP3AQRgFto91lckyGCBYENnaw=s88-c-k-c0x00ffffff-no-rj",
                            "display_name": null,
                            "id": "UCjoZE_5A9tO470CK3G6U7dg",
                            "is_verified": false,
                            "url": "https://www.youtube.com/channel/UCjoZE_5A9tO470CK3G6U7dg",
                            "username": "CTwGary"
                          },
                          "edited_at": null,
                          "id": "UgxHbErLhWMUy5GlFnp4AaABAg",
                          "is_by_post_author": false,
                          "is_edited": false,
                          "is_liked_by_author": false,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": 0,
                            "reply_count": 0
                          },
                          "parent_id": null,
                          "platform": "youtube",
                          "platform_specific": {},
                          "post_id": "jNQXAC9IVRw",
                          "published_at": "2026-10-26T18:58:19Z",
                          "text": "I can’t believe it, but it’s 21 years old now",
                          "unknown_fields": [],
                          "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw&lc=UgxHbErLhWMUy5GlFnp4AaABAg"
                        },
                        {
                          "approximate_fields": [
                            "published_at"
                          ],
                          "author": {
                            "avatar_url": "https://yt3.ggpht.com/Ar50xvd1O4GCXVttK6DgX0Y0cuhBl2b_HUFQjh-gajKbmS-qjuNAHOT5fw_RX_DS5gzfphkcKAI=s88-c-k-c0x00ffffff-no-rj",
                            "display_name": null,
                            "id": "UCFgjcRO4y8XFQL7E8_TcLlg",
                            "is_verified": false,
                            "url": "https://www.youtube.com/channel/UCFgjcRO4y8XFQL7E8_TcLlg",
                            "username": "Nihal-poke"
                          },
                          "edited_at": null,
                          "id": "UgzLOxwwIAUe0jUI4RR4AaABAg",
                          "is_by_post_author": false,
                          "is_edited": false,
                          "is_liked_by_author": false,
                          "is_pinned": false,
                          "metrics": {
                            "like_count": 0,
                            "reply_count": 0
                          },
                          "parent_id": null,
                          "platform": "youtube",
                          "platform_specific": {},
                          "post_id": "jNQXAC9IVRw",
                          "published_at": "2026-10-26T18:58:19Z",
                          "text": "I watch this video many times 😭",
                          "unknown_fields": [],
                          "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw&lc=UgzLOxwwIAUe0jUI4RR4AaABAg"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "youtube",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 316,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "jNQXAC9IVRw",
                          "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": true,
                        "next_cursor": "c1.EXAMPLE_CURSOR",
                        "next_cursor_expires_at": "2026-10-26T12:00:00Z",
                        "end_reason": null
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/YoutubeCommentsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Newest or top first, with likes and reply counts",
        "tags": [
          "YouTube"
        ],
        "x-socialtap-endpoint": "youtube.comments",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "orders": {
            "newest": "newest first",
            "popular": "YouTube's Top comments ranking"
          },
          "page_max": 20,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "comment",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/youtube/engagement": {
      "get": {
        "description": "Returns a YouTube channel's views per upload, median views and posting cadence, computed over its latest videos or shorts, in one request. You also get the channel's profile, each upload with its counts and how its views compare with the channel's typical upload, likes per upload where YouTube shows them, and the newest and oldest upload in the sample. Accepts a handle, any channel link or a channel ID.\n\nReturns `{data, meta}`: `data` is a `Engagement` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/youtube/engagement/ (Markdown: https://socialtap.dev/docs/reference/youtube/engagement/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/youtube/engagement/index.md)",
          "url": "https://socialtap.dev/docs/reference/youtube/engagement/"
        },
        "operationId": "youtube.engagement.get",
        "parameters": [
          {
            "description": "YouTube channel: a handle with or without the @ (NASA, @NASA), any channel link (youtube.com/@NASA, youtube.com/channel/UC…, the legacy youtube.com/c/<name>, youtube.com/user/<name> and youtube.com/<name> links, with any tab or view after them, and m. or music. hosts), a bare UC… channel ID, or c/<name>, user/<name> or vanity/<name>. Handles are case-insensitive.",
            "example": "@MrBeast",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "YouTube channel: a handle with or without the @ (NASA, @NASA), any channel link (youtube.com/@NASA, youtube.com/channel/UC…, the legacy youtube.com/c/<name>, youtube.com/user/<name> and youtube.com/<name> links, with any tab or view after them, and m. or music. hosts), a bare UC… channel ID, or c/<name>, user/<name> or vanity/<name>. Handles are case-insensitive.",
              "examples": [
                "@NASA"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "The uploads the figures cover: the channel's latest videos (default) or its latest shorts.",
            "example": "shorts",
            "in": "query",
            "name": "tab",
            "schema": {
              "description": "The uploads the figures cover: the channel's latest videos (default) or its latest shorts.",
              "enum": [
                "videos",
                "shorts"
              ],
              "examples": [
                "shorts"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [],
                        "bottom_post_id": null,
                        "id": "UCX6OQ3DkcsbYNE6H8uQQuVA",
                        "metrics": {
                          "comment_to_like_ratio": null,
                          "comments_per_post": null,
                          "counted_post_count": 15,
                          "engagement_rate": null,
                          "engagement_rate_stddev": null,
                          "formats": [
                            {
                              "counted_post_count": 15,
                              "engagement_rate": null,
                              "interactions_per_post": null,
                              "type": "video",
                              "views_per_post": 107547782.4
                            }
                          ],
                          "interactions_per_post": null,
                          "likes_per_post": 2063973.27,
                          "median_engagement_rate": null,
                          "median_views_per_post": 85200657,
                          "posts_per_week": 0.77,
                          "quotes_per_post": null,
                          "rated_post_count": 0,
                          "reposts_per_post": null,
                          "sampled_post_count": 15,
                          "saves_per_post": null,
                          "shares_per_post": null,
                          "view_engagement_rate": null,
                          "views_per_post": 107547782.4
                        },
                        "newest_post_at": "2026-10-30T17:00:04Z",
                        "oldest_post_at": "2026-06-24T16:00:14Z",
                        "platform": "youtube",
                        "platform_specific": {},
                        "posts": [
                          {
                            "engagement_rate": null,
                            "engagement_vs_median": null,
                            "is_counted": true,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": null,
                                "display_name": "MrBeast",
                                "id": "UCX6OQ3DkcsbYNE6H8uQQuVA",
                                "is_verified": null,
                                "url": "https://www.youtube.com/channel/UCX6OQ3DkcsbYNE6H8uQQuVA",
                                "username": null
                              },
                              "coauthors": [],
                              "duration_ms": null,
                              "hashtags": [],
                              "id": "41UzbuW6wJs",
                              "is_nsfw": null,
                              "is_pinned": null,
                              "is_sponsored": null,
                              "language": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": null,
                                  "height": 360,
                                  "thumbnail_url": "https://i.ytimg.com/vi/41UzbuW6wJs/hqdefault.jpg",
                                  "type": "video",
                                  "url": null,
                                  "width": 480
                                }
                              ],
                              "mentions": [],
                              "metrics": {
                                "comment_count": null,
                                "like_count": 754355,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": null,
                                "share_count": null,
                                "view_count": 46591207
                              },
                              "platform": "youtube",
                              "platform_specific": {
                                "youtube": {
                                  "author_subscriber_count": null,
                                  "category": null,
                                  "chapters": [],
                                  "description_links": [],
                                  "is_age_restricted": null,
                                  "is_live_now": null,
                                  "is_paywalled": null,
                                  "is_unlisted": null,
                                  "keywords": [],
                                  "live_ended_at": null,
                                  "live_started_at": null,
                                  "scheduled_start_at": null
                                }
                              },
                              "platform_type": "short",
                              "published_at": "2026-10-30T17:00:04Z",
                              "text": null,
                              "thumbnail_url": "https://i.ytimg.com/vi/41UzbuW6wJs/hqdefault.jpg",
                              "title": "Can A Robot Do My Chores?",
                              "type": "video",
                              "unknown_fields": [
                                "coauthors",
                                "platform_specific.youtube.keywords",
                                "platform_specific.youtube.chapters"
                              ],
                              "url": "https://www.youtube.com/shorts/41UzbuW6wJs"
                            },
                            "view_engagement_rate": null,
                            "views_vs_median": 0.55
                          },
                          {
                            "engagement_rate": null,
                            "engagement_vs_median": null,
                            "is_counted": true,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": null,
                                "display_name": "MrBeast",
                                "id": "UCX6OQ3DkcsbYNE6H8uQQuVA",
                                "is_verified": null,
                                "url": "https://www.youtube.com/channel/UCX6OQ3DkcsbYNE6H8uQQuVA",
                                "username": null
                              },
                              "coauthors": [],
                              "duration_ms": null,
                              "hashtags": [],
                              "id": "mND4T0lzg_g",
                              "is_nsfw": null,
                              "is_pinned": null,
                              "is_sponsored": null,
                              "language": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": null,
                                  "height": 360,
                                  "thumbnail_url": "https://i.ytimg.com/vi/mND4T0lzg_g/hqdefault.jpg",
                                  "type": "video",
                                  "url": null,
                                  "width": 480
                                }
                              ],
                              "mentions": [],
                              "metrics": {
                                "comment_count": null,
                                "like_count": 926584,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": null,
                                "share_count": null,
                                "view_count": 32834425
                              },
                              "platform": "youtube",
                              "platform_specific": {
                                "youtube": {
                                  "author_subscriber_count": null,
                                  "category": null,
                                  "chapters": [],
                                  "description_links": [],
                                  "is_age_restricted": null,
                                  "is_live_now": null,
                                  "is_paywalled": null,
                                  "is_unlisted": null,
                                  "keywords": [],
                                  "live_ended_at": null,
                                  "live_started_at": null,
                                  "scheduled_start_at": null
                                }
                              },
                              "platform_type": "short",
                              "published_at": "2026-10-23T18:00:08Z",
                              "text": null,
                              "thumbnail_url": "https://i.ytimg.com/vi/mND4T0lzg_g/hqdefault.jpg",
                              "title": "How People Treat You Based on Subscribers",
                              "type": "video",
                              "unknown_fields": [
                                "coauthors",
                                "platform_specific.youtube.keywords",
                                "platform_specific.youtube.chapters"
                              ],
                              "url": "https://www.youtube.com/shorts/mND4T0lzg_g"
                            },
                            "view_engagement_rate": null,
                            "views_vs_median": 0.39
                          },
                          {
                            "engagement_rate": null,
                            "engagement_vs_median": null,
                            "is_counted": true,
                            "post": {
                              "approximate_fields": [],
                              "author": {
                                "avatar_url": null,
                                "display_name": "MrBeast",
                                "id": "UCX6OQ3DkcsbYNE6H8uQQuVA",
                                "is_verified": null,
                                "url": "https://www.youtube.com/channel/UCX6OQ3DkcsbYNE6H8uQQuVA",
                                "username": null
                              },
                              "coauthors": [],
                              "duration_ms": null,
                              "hashtags": [],
                              "id": "Y8IJi7iP5vk",
                              "is_nsfw": null,
                              "is_pinned": null,
                              "is_sponsored": null,
                              "language": null,
                              "media": [
                                {
                                  "alt_text": null,
                                  "duration_ms": null,
                                  "expires_at": null,
                                  "height": 360,
                                  "thumbnail_url": "https://i.ytimg.com/vi/Y8IJi7iP5vk/hqdefault.jpg",
                                  "type": "video",
                                  "url": null,
                                  "width": 480
                                }
                              ],
                              "mentions": [],
                              "metrics": {
                                "comment_count": null,
                                "like_count": 1213153,
                                "quote_count": null,
                                "repost_count": null,
                                "save_count": null,
                                "share_count": null,
                                "view_count": 138479209
                              },
                              "platform": "youtube",
                              "platform_specific": {
                                "youtube": {
                                  "author_subscriber_count": null,
                                  "category": null,
                                  "chapters": [],
                                  "description_links": [],
                                  "is_age_restricted": null,
                                  "is_live_now": null,
                                  "is_paywalled": null,
                                  "is_unlisted": null,
                                  "keywords": [],
                                  "live_ended_at": null,
                                  "live_started_at": null,
                                  "scheduled_start_at": null
                                }
                              },
                              "platform_type": "short",
                              "published_at": "2026-10-16T16:00:02Z",
                              "text": null,
                              "thumbnail_url": "https://i.ytimg.com/vi/Y8IJi7iP5vk/hqdefault.jpg",
                              "title": "Last To Fall Wins",
                              "type": "video",
                              "unknown_fields": [
                                "coauthors",
                                "platform_specific.youtube.keywords",
                                "platform_specific.youtube.chapters"
                              ],
                              "url": "https://www.youtube.com/shorts/Y8IJi7iP5vk"
                            },
                            "view_engagement_rate": null,
                            "views_vs_median": 1.63
                          }
                        ],
                        "profile": {
                          "approximate_fields": [
                            "created_at",
                            "metrics.follower_count"
                          ],
                          "avatar_url": "https://yt3.googleusercontent.com/nxYrc_1_2f77DoBadyxMTmv7ZpRZapHR5jbuYe7PlPd5cIRJxtNNEYyOC0ZsxaDyJJzXrnJiuDE=s900-c-k-c0x00ffffff-no-rj",
                          "banner_url": "https://yt3.googleusercontent.com/mHMO_eEMp0dPvh0ADwXhPXNYb_GnjSVsLI8biqF1CpxT8OPl7izhNQsDPD3JHhd5y5Mg9GrP=w2560-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
                          "bio": "SUBSCRIBE FOR A COOKIE!\nNew MrBeast or MrBeast Gaming video every single Saturday at noon eastern time!\nAccomplishments:\n- Raised $20,000,000 To Plant 20,000,000 Trees\n- Removed 30,000,000 pounds of trash from the ocean\n- Helped 2,000 people walk again\n- Helped 1,000 blind people…",
                          "category": null,
                          "country_code": "US",
                          "created_at": "2012-02-19T08:00:00Z",
                          "display_name": "MrBeast",
                          "external_links": [
                            {
                              "title": "Follow",
                              "url": "https://www.instagram.com/mrbeast/"
                            },
                            {
                              "title": "Twitter",
                              "url": "https://twitter.com/MrBeast"
                            },
                            {
                              "title": "Facebook",
                              "url": "https://facebook.com/mrbeast/"
                            }
                          ],
                          "id": "UCX6OQ3DkcsbYNE6H8uQQuVA",
                          "is_private": false,
                          "is_verified": true,
                          "location": "United States",
                          "metrics": {
                            "follower_count": 524000000,
                            "following_count": null,
                            "post_count": 1011,
                            "total_like_count": null,
                            "total_view_count": 145430387555
                          },
                          "platform": "youtube",
                          "platform_specific": {
                            "youtube": {
                              "is_business_email_listed": true,
                              "is_official_artist_channel": false,
                              "is_subscriber_count_hidden": false,
                              "keywords": [
                                "mrbeast6000",
                                "beast",
                                "mrbeast"
                              ]
                            }
                          },
                          "type": "unknown",
                          "unknown_fields": [],
                          "url": "https://www.youtube.com/@MrBeast",
                          "username": "MrBeast"
                        },
                        "top_post_id": null,
                        "unknown_fields": [],
                        "url": "https://www.youtube.com/@MrBeast"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "youtube",
                        "source": "page",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 697,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "UCX6OQ3DkcsbYNE6H8uQQuVA",
                          "url": "https://www.youtube.com/@MrBeast"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/YoutubeEngagementResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Views per upload, cadence and outlier videos",
        "tags": [
          "YouTube"
        ],
        "x-socialtap-endpoint": "youtube.engagement",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "engagement",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/youtube/post": {
      "get": {
        "description": "Returns a public YouTube video, short or live stream from its link or ID, with exact view, like and comment counts. It also has the title, description with its hashtags and links, exact publish time, duration, thumbnail, the channel and any collaborating channels, and YouTube's category, tags, chapters and live stream times. Accepts any YouTube video link or a bare video ID.\n\nReturns `{data, meta}`: `data` is a `Post` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/youtube/post/ (Markdown: https://socialtap.dev/docs/reference/youtube/post/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/youtube/post/index.md)",
          "url": "https://socialtap.dev/docs/reference/youtube/post/"
        },
        "operationId": "youtube.post.get",
        "parameters": [
          {
            "description": "YouTube video, short or live stream URL (watch, youtu.be, shorts, live, embed; m. and music. hosts) or an 11-character video ID.",
            "example": "https://youtube.com/shorts/3cWm9B_0_kI?feature=share",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "YouTube video, short or live stream URL (watch, youtu.be, shorts, live, embed; m. and music. hosts) or an 11-character video ID.",
              "examples": [
                "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "platform_specific.youtube.author_subscriber_count"
                        ],
                        "author": {
                          "avatar_url": "https://yt3.ggpht.com/nxYrc_1_2f77DoBadyxMTmv7ZpRZapHR5jbuYe7PlPd5cIRJxtNNEYyOC0ZsxaDyJJzXrnJiuDE=s176-c-k-c0x00ffffff-no-rj",
                          "display_name": "MrBeast",
                          "id": "UCX6OQ3DkcsbYNE6H8uQQuVA",
                          "is_verified": true,
                          "url": "https://www.youtube.com/@MrBeast",
                          "username": "MrBeast"
                        },
                        "coauthors": [],
                        "duration_ms": 20000,
                        "hashtags": [],
                        "id": "3cWm9B_0_kI",
                        "is_nsfw": false,
                        "is_pinned": null,
                        "is_sponsored": null,
                        "language": null,
                        "media": [
                          {
                            "alt_text": null,
                            "duration_ms": 20000,
                            "expires_at": null,
                            "height": null,
                            "thumbnail_url": "https://i.ytimg.com/vi/3cWm9B_0_kI/maxresdefault.jpg?sqp=-oaymwEoCIAKENAF8quKqQMcGADwAQH4AbYIgAKAD4oCDAgAEAEYRiBlKA8wDw==&rs=AOn4CLD2HeSN5ZikYi7hBi3SC7913d9CWQ",
                            "type": "video",
                            "url": null,
                            "width": null
                          }
                        ],
                        "mentions": [],
                        "metrics": {
                          "comment_count": 37974,
                          "like_count": 13520602,
                          "quote_count": null,
                          "repost_count": null,
                          "save_count": null,
                          "share_count": null,
                          "view_count": 731918538
                        },
                        "platform": "youtube",
                        "platform_specific": {
                          "youtube": {
                            "author_subscriber_count": 524000000,
                            "category": "Entertainment",
                            "chapters": [],
                            "description_links": [],
                            "is_age_restricted": false,
                            "is_live_now": false,
                            "is_paywalled": false,
                            "is_unlisted": false,
                            "keywords": [],
                            "live_ended_at": null,
                            "live_started_at": null,
                            "scheduled_start_at": null
                          }
                        },
                        "platform_type": "short",
                        "published_at": "2024-12-27T19:00:00Z",
                        "text": null,
                        "thumbnail_url": "https://i.ytimg.com/vi/3cWm9B_0_kI/maxresdefault.jpg?sqp=-oaymwEoCIAKENAF8quKqQMcGADwAQH4AbYIgAKAD4oCDAgAEAEYRiBlKA8wDw==&rs=AOn4CLD2HeSN5ZikYi7hBi3SC7913d9CWQ",
                        "title": "How Many People To Stop Ronaldo?",
                        "type": "video",
                        "unknown_fields": [],
                        "url": "https://www.youtube.com/shorts/3cWm9B_0_kI"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "youtube",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 1193,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "3cWm9B_0_kI",
                          "url": "https://www.youtube.com/shorts/3cWm9B_0_kI"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/YoutubePostResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Video or short with exact view, like and comment counts",
        "tags": [
          "YouTube"
        ],
        "x-socialtap-endpoint": "youtube.post",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "api"
            },
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "page"
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/youtube/posts": {
      "get": {
        "description": "Returns a public YouTube channel's videos, shorts or live streams a page at a time, newest, oldest or most popular first. Each upload has its link, title, thumbnail, length, views and upload time, and the newest also have exact times, view and like counts and descriptions. Accepts a handle, any channel link or a channel ID.\n\nReturns `{data, page, meta}`: `data` holds up to 48 `Post` items (the shared schema, the same on every platform), newest first with sort=newest (the default), oldest first with sort=oldest, YouTube's Popular order (most viewed first) with sort=popular. For the next page repeat the request with `cursor` set to `page.next_cursor` until `page.has_more` is false.\n\n**Pricing:** 1 credit per successful page. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/youtube/posts/ (Markdown: https://socialtap.dev/docs/reference/youtube/posts/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/youtube/posts/index.md)",
          "url": "https://socialtap.dev/docs/reference/youtube/posts/"
        },
        "operationId": "youtube.posts.list",
        "parameters": [
          {
            "description": "YouTube channel: a handle with or without the @, any channel link (@handle, /channel/UC…, legacy /c/, /user/ and root vanity links, any tab, m. and music. hosts), a bare UC… channel ID, or c/<name>, user/<name>, vanity/<name>.",
            "example": "@jawed",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "YouTube channel: a handle with or without the @, any channel link (@handle, /channel/UC…, legacy /c/, /user/ and root vanity links, any tab, m. and music. hosts), a bare UC… channel ID, or c/<name>, user/<name>, vanity/<name>.",
              "examples": [
                "@MrBeast"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "The channel tab to list: videos (default), shorts or live (upcoming, live and past streams).",
            "example": "shorts",
            "in": "query",
            "name": "tab",
            "schema": {
              "description": "The channel tab to list: videos (default), shorts or live (upcoming, live and past streams).",
              "enum": [
                "videos",
                "shorts",
                "live"
              ],
              "examples": [
                "shorts"
              ],
              "type": "string"
            }
          },
          {
            "description": "Order of the results. newest (default), popular (most viewed first) or oldest.",
            "example": "",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "newest",
              "description": "Order of the results. newest (default), popular (most viewed first) or oldest.",
              "enum": [
                "newest",
                "popular",
                "oldest"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Beyond the newest uploads published_at is approximate (\"3 weeks ago\"), to the day, so it is compared by day there: send a date. Uploads up to one label unit older may be included. Not with tab=shorts.",
            "example": "2026-10-01",
            "in": "query",
            "name": "since",
            "schema": {
              "description": "Only items at or after this time: RFC 3339 (2026-10-01T12:00:00Z) or a date (2026-10-01, midnight UTC). On newest-first lists, paging stops when it is reached, so later pages are not fetched or charged. Beyond the newest uploads published_at is approximate (\"3 weeks ago\"), to the day, so it is compared by day there: send a date. Uploads up to one label unit older may be included. Not with tab=shorts.",
              "examples": [
                "2026-10-01"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Not with tab=shorts.",
            "example": "2026-10-08",
            "in": "query",
            "name": "until",
            "schema": {
              "description": "Only items before this time (exclusive): RFC 3339 or a date (midnight UTC). Not with tab=shorts.",
              "examples": [
                "2026-10-08"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.",
            "example": 48,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 48,
              "maximum": 48,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "page.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": [
                        {
                          "approximate_fields": [],
                          "author": {
                            "avatar_url": "https://yt3.googleusercontent.com/uI3VE4PVqvCy0xnWLqMJnEzyBUm3T8VHOCp4ee-1RxdHqKXCdUE_qXYQnpf9AfuEoIPactVyDhM=s900-c-k-c0x00ffffff-no-rj",
                            "display_name": "jawed",
                            "id": "UC4QobU6STFB0P71PMvOGN5A",
                            "is_verified": null,
                            "url": "https://www.youtube.com/channel/UC4QobU6STFB0P71PMvOGN5A",
                            "username": "jawed"
                          },
                          "coauthors": [],
                          "duration_ms": 19000,
                          "hashtags": [],
                          "id": "jNQXAC9IVRw",
                          "is_nsfw": null,
                          "is_pinned": null,
                          "is_sponsored": null,
                          "language": null,
                          "media": [
                            {
                              "alt_text": null,
                              "duration_ms": 19000,
                              "expires_at": null,
                              "height": 360,
                              "thumbnail_url": "https://i.ytimg.com/vi/jNQXAC9IVRw/hqdefault.jpg",
                              "type": "video",
                              "url": null,
                              "width": 480
                            }
                          ],
                          "mentions": [],
                          "metrics": {
                            "comment_count": null,
                            "like_count": 20117813,
                            "quote_count": null,
                            "repost_count": null,
                            "save_count": null,
                            "share_count": null,
                            "view_count": 446865949
                          },
                          "platform": "youtube",
                          "platform_specific": {
                            "youtube": {
                              "author_subscriber_count": null,
                              "category": null,
                              "chapters": [],
                              "description_links": [
                                "https://www.youtube.com/watch?v=0PT5c1z3LL8",
                                "https://www.youtube.com/watch?v=RRBN_4L09Mg"
                              ],
                              "is_age_restricted": null,
                              "is_live_now": null,
                              "is_paywalled": null,
                              "is_unlisted": null,
                              "keywords": [],
                              "live_ended_at": null,
                              "live_started_at": null,
                              "scheduled_start_at": null
                            }
                          },
                          "platform_type": "video",
                          "published_at": "2005-04-24T03:31:52Z",
                          "text": "Microplastics are accumulating in human brains at an alarming rate\nhttps://www.youtube.com/watch?v=0PT5c1z3LL8\n\n“Nanoplastics and Human Health” with Matthew J Campen, PhD, MSPH\nhttps://www.youtube.com/watch?v=RRBN_4L09Mg\n\n00:00 Intro\n00:05 The cool thing\n00:17 End",
                          "thumbnail_url": "https://i.ytimg.com/vi/jNQXAC9IVRw/hqdefault.jpg",
                          "title": "Me at the zoo",
                          "type": "video",
                          "unknown_fields": [
                            "coauthors",
                            "platform_specific.youtube.keywords",
                            "platform_specific.youtube.chapters"
                          ],
                          "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw"
                        }
                      ],
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "youtube",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 442,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "UC4QobU6STFB0P71PMvOGN5A",
                          "url": "https://www.youtube.com/@jawed"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      },
                      "page": {
                        "has_more": false,
                        "next_cursor": null,
                        "next_cursor_expires_at": null,
                        "end_reason": "end"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/YoutubePostsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_cursor": {
                    "$ref": "#/components/examples/invalid_cursor"
                  },
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.\n\n`invalid_cursor`: The cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it. Repeat the original request without cursor to start the list again.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Videos, shorts and live streams of a channel",
        "tags": [
          "YouTube"
        ],
        "x-socialtap-endpoint": "youtube.posts",
        "x-socialtap-pagination": {
          "cursor_expires_at": "page.next_cursor_expires_at",
          "cursor_param": "cursor",
          "cursor_ttl_s": 3600,
          "has_more": "page.has_more",
          "limit_param": "limit",
          "next_cursor": "page.next_cursor",
          "order": "newest first",
          "orders": {
            "newest": "newest first",
            "oldest": "oldest first",
            "popular": "YouTube's Popular order (most viewed first)"
          },
          "page_max": 48,
          "style": "cursor"
        },
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "page"
        },
        "x-socialtap-resource": "post",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/youtube/profile": {
      "get": {
        "description": "Returns a public YouTube channel from its handle, link or ID, with its subscriber count, exact video and view counts, and its About panel links. It also has the channel ID, handle, name, description, keywords, avatar, banner, verification badge, country and join date. Accepts a handle with or without the @, any channel link with any tab (@handle, /channel/UC…, the legacy /c/, /user/ and root vanity links), or a bare channel ID.\n\nReturns `{data, meta}`: `data` is a `Profile` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/youtube/profile/ (Markdown: https://socialtap.dev/docs/reference/youtube/profile/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/youtube/profile/index.md)",
          "url": "https://socialtap.dev/docs/reference/youtube/profile/"
        },
        "operationId": "youtube.profile.get",
        "parameters": [
          {
            "description": "YouTube channel: a handle with or without the @ (NASA, @NASA), any channel link (youtube.com/@NASA, youtube.com/channel/UC…, the legacy youtube.com/c/<name>, youtube.com/user/<name> and youtube.com/<name> links, with any tab or view after them such as /videos, /playlists, /posts or /about, and m. or music. hosts), a bare UC… channel ID, or c/<name>, user/<name> or vanity/<name>. Handles are case-insensitive. A bare string is always a handle, even one shaped like a video ID.",
            "example": "@NASA",
            "in": "query",
            "name": "handle",
            "required": true,
            "schema": {
              "description": "YouTube channel: a handle with or without the @ (NASA, @NASA), any channel link (youtube.com/@NASA, youtube.com/channel/UC…, the legacy youtube.com/c/<name>, youtube.com/user/<name> and youtube.com/<name> links, with any tab or view after them such as /videos, /playlists, /posts or /about, and m. or music. hosts), a bare UC… channel ID, or c/<name>, user/<name> or vanity/<name>. Handles are case-insensitive. A bare string is always a handle, even one shaped like a video ID.",
              "examples": [
                "@NASA"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "approximate_fields": [
                          "created_at",
                          "metrics.follower_count"
                        ],
                        "avatar_url": "https://yt3.googleusercontent.com/eIf5fNPcIcj9ig-wZBeq4stFy1lgjWTW1nLT5dYlFkHZprZ03QBiMcbpwNMB6XSBjrSFGtAGQg=s900-c-k-c0x00ffffff-no-rj",
                        "banner_url": "https://yt3.googleusercontent.com/y8Srh-oCcilLvBO8jAPI546m1bn0puA5DIvQiBZ1cSxc_rZfKxKSFlTCtoCQCtB6viUf1NGsaQ=w2560-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
                        "bio": "NASA's mission is to pioneer the future in space exploration, scientific discovery, and aeronautics research.\n\nTo do that, we have worked around the world—and off it—for more than 60 years, searching for answers to fundamental questions about our place in the universe. We're expl…",
                        "category": null,
                        "country_code": null,
                        "created_at": "2008-06-03T07:00:00Z",
                        "display_name": "NASA",
                        "external_links": [
                          {
                            "title": "nasa.gov",
                            "url": "https://www.nasa.gov"
                          },
                          {
                            "title": "X",
                            "url": "https://x.com/nasa"
                          },
                          {
                            "title": "Facebook",
                            "url": "https://www.facebook.com/NASA"
                          }
                        ],
                        "id": "UCLA_DiR1FfKNvjuUpBHmylQ",
                        "is_private": false,
                        "is_verified": true,
                        "location": null,
                        "metrics": {
                          "follower_count": 15100000,
                          "following_count": null,
                          "post_count": 6194,
                          "total_like_count": null,
                          "total_view_count": 1132473139
                        },
                        "platform": "youtube",
                        "platform_specific": {
                          "youtube": {
                            "is_business_email_listed": null,
                            "is_official_artist_channel": false,
                            "is_subscriber_count_hidden": false,
                            "keywords": [
                              "nasa",
                              "space",
                              "iss"
                            ]
                          }
                        },
                        "type": "unknown",
                        "unknown_fields": [],
                        "url": "https://www.youtube.com/@NASA",
                        "username": "NASA"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "youtube",
                        "source": "api",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 456,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "profile",
                          "id": "UCLA_DiR1FfKNvjuUpBHmylQ",
                          "url": "https://www.youtube.com/@NASA"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/YoutubeProfileResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Subscribers, exact view counts and social links",
        "tags": [
          "YouTube"
        ],
        "x-socialtap-endpoint": "youtube.profile",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 1,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": ""
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "profile",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    },
    "/v1/youtube/transcript": {
      "get": {
        "description": "Returns the timed transcript of a public YouTube video, short or live replay, from its captions or, when it has none, its audio. Send the video's link or ID. Each segment has its start and end time, and text holds the whole transcript.\n\nReturns `{data, meta}`: `data` is a `Transcript` object (the shared schema, the same on every platform). Null means unknown.\n\n**Pricing:** 1 credit (captions) or 2 credits + 2 per started minute of media (speech-to-text) per successful request. Failed requests and cache hits are free.\n\n**Docs:** https://socialtap.dev/docs/reference/youtube/transcript/ (Markdown: https://socialtap.dev/docs/reference/youtube/transcript/index.md).",
        "externalDocs": {
          "description": "Endpoint docs (Markdown: https://socialtap.dev/docs/reference/youtube/transcript/index.md)",
          "url": "https://socialtap.dev/docs/reference/youtube/transcript/"
        },
        "operationId": "youtube.transcript.get",
        "parameters": [
          {
            "description": "YouTube video URL (watch, youtu.be, shorts, live, embed, m./music. hosts) or an 11-character video ID.",
            "example": "dQw4w9WgXcQ",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "YouTube video URL (watch, youtu.be, shorts, live, embed, m./music. hosts) or an 11-character video ID.",
              "examples": [
                "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
              ],
              "maxLength": 2048,
              "type": "string"
            }
          },
          {
            "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). Selects the caption track; a manual track is preferred over an auto-generated one. Default: the video's original-language manual track, else its auto-generated track.",
            "example": "en",
            "in": "query",
            "name": "lang",
            "schema": {
              "description": "Preferred language: a BCP-47 tag such as en or pt-BR (case-insensitive; _ is read as -). Selects the caption track; a manual track is preferred over an auto-generated one. Default: the video's original-language manual track, else its auto-generated track.",
              "examples": [
                "en"
              ],
              "type": "string"
            }
          },
          {
            "description": "Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.",
            "in": "query",
            "name": "max_age",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Return only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.",
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.",
            "example": "respond-async",
            "in": "header",
            "name": "prefer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "example": {
                    "description": "Long arrays and strings are shortened for display; real responses are complete.",
                    "summary": "A real response (recorded fixture)",
                    "value": {
                      "data": {
                        "available_languages": [
                          "en",
                          "de-DE",
                          "ja"
                        ],
                        "duration_ms": 213000,
                        "id": "dQw4w9WgXcQ",
                        "is_auto_generated": false,
                        "language": "en",
                        "platform": "youtube",
                        "platform_specific": {},
                        "segments": [
                          {
                            "end_ms": 3040,
                            "start_ms": 1360,
                            "text": "[♪♪♪]"
                          },
                          {
                            "end_ms": 21880,
                            "start_ms": 18640,
                            "text": "♪ We're no strangers to love ♪"
                          },
                          {
                            "end_ms": 26960,
                            "start_ms": 22640,
                            "text": "♪ You know the rules and so do I ♪"
                          }
                        ],
                        "source": "captions",
                        "text": "[♪♪♪] ♪ We're no strangers to love ♪ ♪ You know the rules and so do I ♪ ♪ A full commitment's what I'm thinking of ♪ ♪ You wouldn't get this from any other guy ♪ ♪ I just wanna tell you how I'm feeling ♪ ♪ Gotta make you understand ♪ ♪ Never gonna give you up ♪ ♪ Never gonna let …",
                        "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
                      },
                      "meta": {
                        "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
                        "platform": "youtube",
                        "source": "captions",
                        "is_cached": false,
                        "credits_charged": 1,
                        "latency_ms": 308,
                        "fetched_at": "2026-10-25T12:00:00Z",
                        "input": {
                          "kind": "video",
                          "id": "dQw4w9WgXcQ",
                          "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
                        },
                        "credits_remaining": 9999,
                        "client_request_id": null,
                        "warnings": []
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/YoutubeTranscriptResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "age": {
                "$ref": "#/components/headers/age"
              },
              "allow": {
                "$ref": "#/components/headers/allow"
              },
              "deprecation": {
                "$ref": "#/components/headers/deprecation"
              },
              "link": {
                "$ref": "#/components/headers/link"
              },
              "ratelimit": {
                "$ref": "#/components/headers/ratelimit"
              },
              "ratelimit-policy": {
                "$ref": "#/components/headers/ratelimit-policy"
              },
              "sunset": {
                "$ref": "#/components/headers/sunset"
              },
              "x-client-request-id": {
                "$ref": "#/components/headers/x-client-request-id"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/AsyncAccepted"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalid_input": {
                    "$ref": "#/components/examples/invalid_input"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`invalid_input`: A parameter is missing or malformed, or the link is not one this endpoint takes. Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "examples": {
                  "unauthorized": {
                    "$ref": "#/components/examples/unauthorized"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`unauthorized`: The x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired. Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "insufficient_credits": {
                    "$ref": "#/components/examples/insufficient_credits"
                  },
                  "spend_limit_reached": {
                    "$ref": "#/components/examples/spend_limit_reached"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`insufficient_credits`: The account does not have enough credits for this request. Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.\n\n`spend_limit_reached`: The API key reached its spend limit for this period. The account may still have credits. Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "examples": {
                  "forbidden": {
                    "$ref": "#/components/examples/forbidden"
                  },
                  "private_or_unavailable": {
                    "$ref": "#/components/examples/private_or_unavailable"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`forbidden`: The API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code. Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.\n\n`private_or_unavailable`: The item exists but is not public: it is private, age- or region-restricted, or needs a login to view. It shares 403 with forbidden (which is about the key), so branch on the code. Only public items can be fetched. Do not retry.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "examples": {
                  "no_transcript": {
                    "$ref": "#/components/examples/no_transcript"
                  },
                  "not_found": {
                    "$ref": "#/components/examples/not_found"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`not_found`: The item does not exist or was deleted. On GET /v1/requests/{id}/response: the response was not kept (details.reason says why). Check the link or ID. Do not retry.\n\n`no_transcript`: The video or audio exists but has no transcript: no caption track and no speech to transcribe. Do not retry. If the platform offers other languages, try one with lang.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "$ref": "#/components/examples/rate_limited"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`rate_limited`: The account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it. Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "examples": {
                  "internal": {
                    "$ref": "#/components/examples/internal"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`internal`: An unexpected error on SocialTap's side. Retry with backoff. If it keeps happening, contact support with the request_id.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "examples": {
                  "upstream_error": {
                    "$ref": "#/components/examples/upstream_error"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_error`: The platform failed, or answered with something we could not read. Retry with backoff. Failed requests are free.",
            "headers": {
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "overloaded": {
                    "$ref": "#/components/examples/overloaded"
                  },
                  "upstream_blocked": {
                    "$ref": "#/components/examples/upstream_blocked"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "`upstream_blocked`: The platform refused every attempt, our own retries included. Retry later with backoff. Failed requests are free.\n\n`overloaded`: SocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged. Retry after the seconds in the retry-after header. Failed requests are free.",
            "headers": {
              "retry-after": {
                "$ref": "#/components/headers/retry-after"
              },
              "x-credits-charged": {
                "$ref": "#/components/headers/x-credits-charged"
              },
              "x-credits-remaining": {
                "$ref": "#/components/headers/x-credits-remaining"
              },
              "x-request-id": {
                "$ref": "#/components/headers/x-request-id"
              }
            }
          }
        },
        "summary": "Timed transcript from captions or audio",
        "tags": [
          "YouTube"
        ],
        "x-socialtap-endpoint": "youtube.transcript",
        "x-socialtap-pricing": {
          "cache_hits_free": true,
          "failed_requests_free": true,
          "max_credits": 122,
          "min_credits": 1,
          "prices": [
            {
              "credits": 1,
              "label": "1 credit",
              "max": 1,
              "per": 0,
              "source": "captions"
            },
            {
              "credits": 2,
              "label": "2 credits + 2 per started minute of media",
              "max": 122,
              "per": 2,
              "source": "asr",
              "unit": "media_minute",
              "unit_max": 60
            }
          ],
          "unit": "request"
        },
        "x-socialtap-resource": "transcript",
        "x-socialtap-retry": {
          "failed_requests_free": true,
          "idempotent": true,
          "retry_after_codes": [
            "rate_limited",
            "overloaded"
          ],
          "retry_after_header": "retry-after",
          "retryable_codes": [
            "rate_limited",
            "upstream_blocked",
            "upstream_error",
            "overloaded",
            "internal"
          ]
        }
      }
    }
  },
  "security": [
    {
      "apiKey": []
    }
  ],
  "servers": [
    {
      "url": "https://socialtap.dev"
    }
  ],
  "tags": [
    {
      "description": "Public Amazon products with their price, list price, seller, rating and monthly sales badge, from any Amazon marketplace. Each comes with its Best Sellers Rank, specifications, variations and images, by product link, short link or ASIN, and the top customer reviews its page shows outside amazon.com. Every seller's offers of a product too, with price, condition, delivery and the seller's rating. Seller profiles add each third-party seller's ratings and the business details it discloses, and influencer storefronts their curations, trending picks, video and photo posts with the products they tag, and idea lists as playlists of products.",
      "name": "Amazon"
    },
    {
      "description": "Apple Music tracks (songs and music videos) with ISRC, composer and audio formats, and albums with their tracklist, label and UPC. Artists with bio, origin and top songs, playlists and radio stations, and the most played charts by country. Search tracks, albums, artists and playlists by keyword, in any country's store.",
      "name": "Apple Music"
    },
    {
      "description": "Public Bluesky profiles with exact follower counts and the DID that survives a rename, and posts with exact likes, replies, reposts, quotes and bookmarks. Get an account's posts and the comments under a post, nested replies included. Search posts by words, author, mention, hashtag, link, language and date.",
      "name": "Bluesky"
    },
    {
      "description": "Public Facebook Pages and profiles, and their posts, reels and photos with exact reaction, comment and share counts. Get a Page's exact follower count, contact details and hours, the comments and replies on any public post, video transcripts, engagement rates, and public groups with their member counts, rules, admins and posts. Find posts, Pages, people and groups by keyword in a search engine's web results, and read each one live from Facebook on request.",
      "name": "Facebook"
    },
    {
      "description": "Ads from Meta's public Ad Library, on Facebook, Instagram, Messenger, Threads and the Audience Network, with creatives, run dates and advertiser. Search ads by keyword, list an advertiser's ads, or get one ad with its EU and UK audience, the payer, reach and spend of political and social-issue ads, and the transcript of its video. Find advertisers by name, with their Page ID and followers.",
      "name": "Facebook Ad Library"
    },
    {
      "description": "Public Facebook Marketplace listings with price, condition, description, photos, seller and delivery options. Search listings by keyword around a location with Marketplace's own filters, and find the places (cities, neighborhoods, postal codes) to search around.",
      "name": "Facebook Marketplace"
    },
    {
      "description": "Public Facebook events with their dates, venue, hosts, categories, ticket link and going and interested counts. Get one by its link, list a Page's events or a city's, or search events by keyword.",
      "name": "Facebook Events"
    },
    {
      "description": "Ads from Google's public Ads Transparency Center, shown on Search, YouTube, Maps, Play and Shopping: one ad with its advertiser, formats, dates and regions, an advertiser's ads, or a website's. Ads shown in Europe and election ads add Google's impressions and targeting, and election ads their spend. Find advertisers by name with their IDs, verification and ad counts, or read the search box's suggestions of advertisers and websites.",
      "name": "Google Ads Transparency Center"
    },
    {
      "description": "Public Instagram profiles with exact follower counts, posts and reels with their likes and views, comments, and transcripts of reels. You also get engagement rates, stories and highlight playlists, similar accounts, hashtags and places with exact post counts, songs and original sounds with the reels that use them, topics and embed code. Search reels and hashtags by keyword, get Instagram's search-box suggestions, find accounts, places and audio in a search engine's web results, and check whether a username is free.",
      "name": "Instagram"
    },
    {
      "description": "Public Kick clips as posts, each with its channel, title, exact views, length, category and playback link, and the broadcast and saved video it was cut from. A clip's transcript comes from speech-to-text on its audio.",
      "name": "Kick"
    },
    {
      "description": "Komi creator pages with everything they show, in order: links, products with prices, discount codes, videos, music releases, podcasts and events. Each page also has its social and contact links, bio and owner's name.",
      "name": "Komi"
    },
    {
      "description": "Public Kwai profiles with exact follower, like and post counts, and posts (short videos) with exact views, likes, comments and shares. Each video comes with its caption, publish time, length, video file and sound. Get one from its link, or an account's videos a page at a time.",
      "name": "Kwai"
    },
    {
      "description": "Lnk.Bio profiles with every link in the list, including those the page loads as you scroll, and the social icons, emails and phone numbers. Each one also has the name, bio, picture, verified badge and the account's own domain.",
      "name": "Lnk.Bio"
    },
    {
      "description": "Public LinkedIn profiles of companies and members: a Page's industry, size, headquarters and exact follower and employee counts, a member's headline, experience, education and skills. Posts and articles come with their text, media, exact reaction and comment counts and top comments. Search companies, people and posts by keyword in a search engine's web results.",
      "name": "LinkedIn"
    },
    {
      "description": "Ads from LinkedIn's public Ad Library in every format, searched by keyword, advertiser, company ID or payer and filtered by country and dates. An ad by its link or ID comes in full with its advertiser, who paid, text and media. Ads shown in the EU and Brazil add their run dates, impressions and targeting.",
      "name": "LinkedIn Ad Library"
    },
    {
      "description": "Linkme profiles with total followers, each social account's handle and follower count, and every link on the page. The emails, phone numbers and street addresses the page lists come too, with the name, bio, picture and verified badge.",
      "name": "Linkme"
    },
    {
      "description": "Linktree profiles with every link on the page in order, each with its type, group and thumbnail, plus the social icons and contact email. Each profile also has the bio, avatar, verified badge, country and join date.",
      "name": "Linktree"
    },
    {
      "description": "Pillar creator pages with every link and its click count, the products, courses and bookings for sale, and the audience the media kit shows per account. Each page also has the creator's social accounts, bio, featured videos and contact email.",
      "name": "Pillar"
    },
    {
      "description": "Pinterest pins (posts) with their pictures and videos, exact saves, reactions and comments, the link each pin points to, its board and the account that first pinned it. Profiles with exact follower, pin and board counts and monthly views. Send a pin's link, a pin.it short link or its ID. Ideas pages are topics, with their related searches, refinements and search counts. Also how many times any web page was saved to Pinterest, by its link, and Pinterest Trends: the top and rising searches by country.",
      "name": "Pinterest"
    },
    {
      "description": "Public Reddit posts with their upvotes, comment counts and media, comment threads with their replies, and user profiles with karma and trophies. You also get subreddits with their rules and weekly visitors, a user's posts and comments, engagement figures over their latest posts, and transcripts of video posts. Search posts and comments by keyword, sitewide or in one subreddit, and find users and subreddits by name or topic.",
      "name": "Reddit"
    },
    {
      "description": "Rumble posts (videos, shorts and live streams) with views, likes and dislikes, their comments and replies, and their transcripts. Channel and user profiles, each account's uploads and engagement rate, and video search by keyword.",
      "name": "Rumble"
    },
    {
      "description": "Public Snapchat profiles with their subscriber count, public Story and saved Stories. Spotlights with their video or image, exact views and likes and a transcript, plus the comments and replies under them.",
      "name": "Snapchat"
    },
    {
      "description": "SoundCloud tracks with exact play, like, repost, comment and download counts, genre, tags, license, and the ISRC, label and UPC that labels fill in. Artists with their bio, exact follower counts and the links they list, and every public track an artist has posted, newest first.",
      "name": "SoundCloud"
    },
    {
      "description": "Spotify tracks with exact play counts, ISRC, songwriter credits and label, and artists with monthly listeners, followers and top cities. Albums with every track's plays, playlists with their followers and each track's BPM and key, and podcasts with ratings and episodes. Search tracks, albums, artists, playlists and podcasts by keyword, or send a Spotify link, URI or ID.",
      "name": "Spotify"
    },
    {
      "description": "Telegram channels, groups and bots with their subscriber or member counts, bio, links and photo. Each channel's posts with their text, media, views and reactions, newest first, or one post by its t.me link. Find channels by topic or name in a search engine's web results, each filled in with its live record on request.",
      "name": "Telegram"
    },
    {
      "description": "Public Threads profiles with exact follower counts, and posts with exact likes, replies, reposts, quotes and shares. Get the comments (replies) under a post and an account's posts with their media. Search posts by keyword and accounts by name or username.",
      "name": "Threads"
    },
    {
      "description": "Public TikTok profiles with exact follower counts, videos and photo posts with their views and likes, comments and transcripts. You also get engagement rates, playlists, effects, LIVE rooms, watermark-free downloads and what's trending by country. Search videos, hashtags and sounds by keyword, get the search box's suggestions for a partial query, and find accounts by keyword, niche or place in a search engine's web results.",
      "name": "TikTok"
    },
    {
      "description": "Ads shown in Europe from TikTok's public ad library, looked up by link or ID or searched by keyword or advertiser. Each ad has its advertiser and who paid, text, media, landing page, days shown, reach, targeting and takedowns. Creative Center's Top Ads board adds the best-performing ads by market, the US included.",
      "name": "TikTok Ad Library"
    },
    {
      "description": "Public TikTok Shop products with their price, discount, variants, stock and units sold, by product link, by store or by keyword search. Reviews come with their star rating, photos and verified-purchase flag. US products only.",
      "name": "TikTok Shop"
    },
    {
      "description": "Truth Social profiles with exact follower counts, bio and links, and each account's posts, its Truths and ReTruths, newest first. Each post has its text, media, link card and poll, with exact reply, ReTruth and like counts.",
      "name": "Truth Social"
    },
    {
      "description": "Public Twitch profiles with exact followers, links, Partner badge and whether the channel is live, with its viewer count. Videos and clips come with exact views, category, chapters and video files. You also get the streams a channel has scheduled and a clip's transcript from speech-to-text.",
      "name": "Twitch"
    },
    {
      "description": "Public X (formerly Twitter) profiles with exact follower counts, and posts with their full text, media and exact views, likes and reposts. Communities come with their rules, admin and exact member count. Find accounts, posts, Communities and hashtags by keyword in a search engine's web results.",
      "name": "X"
    },
    {
      "description": "Public YouTube channel profiles with subscriber counts, and posts: any video, short or live stream with exact view, like and comment counts, or a channel's uploads, newest or most popular first. Get a video's timed transcript, from its captions or its audio, and its comments a page at a time. Engagement adds a channel's views per upload, median views and posting cadence.",
      "name": "YouTube"
    },
    {
      "description": "Live endpoint health.",
      "name": "Status"
    },
    {
      "description": "The account: balance, settings, usage and the credit ledger. Free.",
      "name": "Account"
    },
    {
      "description": "Buy credit packs and start monthly plans (Stripe Checkout), follow a purchase until its credits are added, change or cancel a plan, set up auto top-up and manage the saved card.",
      "name": "Billing"
    },
    {
      "description": "The request log: every endpoint request, with its params, outcome, credits and latency, kept for a while. Free.",
      "name": "Requests"
    },
    {
      "description": "Create, list, update, rotate and revoke API keys: scopes, spend limits, expiry, IP allowlists. Free.",
      "name": "API keys"
    },
    {
      "description": "Background jobs and batches: many requests, or one long one, run with the synchronous path's prices and caches.",
      "name": "Jobs"
    },
    {
      "description": "Webhook endpoints: signed (Standard Webhooks), retried deliveries of events.",
      "name": "Webhooks"
    },
    {
      "description": "Events: what happened in the account (jobs ending, credits running low), kept for a while and delivered by webhooks.",
      "name": "Events"
    },
    {
      "description": "The dashboard's notifications, and which ones email the owner. Free.",
      "name": "Notifications"
    },
    {
      "description": "The account's people: members and their roles (owner, admin, member), email invitations, leaving and handing the account over. The dashboard session only. Free.",
      "name": "Team"
    },
    {
      "description": "Self-serve signup for humans (Google, GitHub or email and password on the sign-in page, then the dashboard) and agents (a key that works once the human confirms). Free.",
      "name": "Signup"
    },
    {
      "description": "The docs and site themselves: feedback on a page, from readers and agents, the site's sign-up funnel and its free tools. Free.",
      "name": "Docs"
    }
  ],
  "webhooks": {
    "api_key.created": {
      "post": {
        "description": "An API key was created (not an account's first keys). The body is the event object (its data a APIKeyEventData); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.api_key_created",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "api_key_id": {
                        "description": "The key (key_…).",
                        "type": "string"
                      },
                      "name": {
                        "description": "Its label.",
                        "type": "string"
                      },
                      "prefix": {
                        "description": "The secret's first characters, to recognize it.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "api_key_id",
                      "name",
                      "prefix"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "api_key.created"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "api_key.created",
        "tags": [
          "Events"
        ]
      }
    },
    "api_key.revoked": {
      "post": {
        "description": "An API key was revoked. The body is the event object (its data a APIKeyEventData); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.api_key_revoked",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "api_key_id": {
                        "description": "The key (key_…).",
                        "type": "string"
                      },
                      "name": {
                        "description": "Its label.",
                        "type": "string"
                      },
                      "prefix": {
                        "description": "The secret's first characters, to recognize it.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "api_key_id",
                      "name",
                      "prefix"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "api_key.revoked"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "api_key.revoked",
        "tags": [
          "Events"
        ]
      }
    },
    "api_key.secret_rotated": {
      "post": {
        "description": "An API key's secret was rotated: the key has a new secret (prefix), the old one works until its overlap ends. The body is the event object (its data a APIKeyEventData); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.api_key_secret_rotated",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "api_key_id": {
                        "description": "The key (key_…).",
                        "type": "string"
                      },
                      "name": {
                        "description": "Its label.",
                        "type": "string"
                      },
                      "prefix": {
                        "description": "The secret's first characters, to recognize it.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "api_key_id",
                      "name",
                      "prefix"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "api_key.secret_rotated"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "api_key.secret_rotated",
        "tags": [
          "Events"
        ]
      }
    },
    "api_key.spend_limit_reached": {
      "post": {
        "description": "An API key's request (or job) was refused for its spend limit, the first time in the limit's interval. The body is the event object (its data a SpendLimitReachedData); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.api_key_spend_limit_reached",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "api_key_id": {
                        "description": "The key (key_…) whose spend limit was reached.",
                        "type": "string"
                      },
                      "api_key_name": {
                        "description": "Its name (null if unreadable; absent from events sent before 2026-10-31).",
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "resets_at": {
                        "description": "Start of the next interval, RFC 3339 UTC: the key can spend again then.",
                        "format": "date-time",
                        "type": "string"
                      },
                      "spend_limit": {
                        "description": "Its spend limit.",
                        "properties": {
                          "amount": {
                            "description": "Most credits the key may spend per interval.",
                            "type": "integer"
                          },
                          "interval": {
                            "description": "Calendar day or month, UTC.",
                            "enum": [
                              "day",
                              "month"
                            ],
                            "type": "string"
                          }
                        },
                        "required": [
                          "amount",
                          "interval"
                        ],
                        "type": "object"
                      },
                      "used": {
                        "description": "Credits the key had used this interval (spent plus held by its requests in flight).",
                        "type": "integer"
                      }
                    },
                    "required": [
                      "api_key_id",
                      "spend_limit",
                      "used",
                      "resets_at"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "api_key.spend_limit_reached"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "api_key.spend_limit_reached",
        "tags": [
          "Events"
        ]
      }
    },
    "auto_topup.failed": {
      "post": {
        "description": "An auto top-up charge failed (declined, or the bank asked the cardholder to confirm it): nothing was charged, auto top-up turned off and the owner was emailed why. It never retries: a person turns it back on. The body is the event object (its data a AutoTopupCharge); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.auto_topup_failed",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "amount_tax": {
                        "description": "The tax in amount_total (Stripe Tax: only where SocialTap collects it); null when amount_total is.",
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "amount_total": {
                        "description": "Charged, tax included, in cents of currency; null when nothing was charged or before it is known.",
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "created_at": {
                        "description": "When the balance crossed the threshold, RFC 3339 UTC.",
                        "format": "date-time",
                        "type": "string"
                      },
                      "credits": {
                        "description": "Credits the pack adds.",
                        "type": "integer"
                      },
                      "currency": {
                        "description": "amount_total's currency (ISO 4217).",
                        "enum": [
                          "usd"
                        ],
                        "type": "string"
                      },
                      "id": {
                        "description": "Top-up ID (atu_…): the ref of its credit_transaction, and on the Stripe payment's metadata.",
                        "type": "string"
                      },
                      "message": {
                        "description": "What the bank or Stripe said, for people; null when reason is.",
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "object": {
                        "description": "Always auto_topup_charge.",
                        "enum": [
                          "auto_topup_charge"
                        ],
                        "type": "string"
                      },
                      "pack": {
                        "description": "The credit pack (catalog pack ID).",
                        "type": "string"
                      },
                      "reason": {
                        "description": "Why it failed (the off_reason it set) or was skipped (monthly_cap, trust_limit: it would have passed rolling_limit_cents); null otherwise.",
                        "enum": [
                          "card_declined",
                          "authentication_required",
                          "no_card",
                          "billing_address_required",
                          "payment_failed",
                          "disputed",
                          "monthly_cap",
                          "trust_limit"
                        ],
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "status": {
                        "description": "processing (the charge is under way), succeeded (paid: its credits were added, once), failed (nothing charged: auto top-up turned off, see reason) or skipped (it would have passed the monthly cap or the 7-day limit: nothing charged, auto top-up stays on).",
                        "enum": [
                          "processing",
                          "succeeded",
                          "failed",
                          "skipped"
                        ],
                        "type": "string"
                      }
                    },
                    "required": [
                      "object",
                      "id",
                      "status",
                      "pack",
                      "credits",
                      "amount_total",
                      "amount_tax",
                      "currency",
                      "reason",
                      "message",
                      "created_at"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "auto_topup.failed"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "auto_topup.failed",
        "tags": [
          "Events"
        ]
      }
    },
    "auto_topup.skipped": {
      "post": {
        "description": "The balance crossed the auto top-up threshold, but buying the pack would have passed the monthly cap (the owner is emailed, once a month) or the account's limit per {trust_window_days} days (the owner is emailed how to lift it, once per {trust_window_days} days): nothing was charged. Auto top-up stays on. The body is the event object (its data a AutoTopupCharge); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.auto_topup_skipped",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "amount_tax": {
                        "description": "The tax in amount_total (Stripe Tax: only where SocialTap collects it); null when amount_total is.",
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "amount_total": {
                        "description": "Charged, tax included, in cents of currency; null when nothing was charged or before it is known.",
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "created_at": {
                        "description": "When the balance crossed the threshold, RFC 3339 UTC.",
                        "format": "date-time",
                        "type": "string"
                      },
                      "credits": {
                        "description": "Credits the pack adds.",
                        "type": "integer"
                      },
                      "currency": {
                        "description": "amount_total's currency (ISO 4217).",
                        "enum": [
                          "usd"
                        ],
                        "type": "string"
                      },
                      "id": {
                        "description": "Top-up ID (atu_…): the ref of its credit_transaction, and on the Stripe payment's metadata.",
                        "type": "string"
                      },
                      "message": {
                        "description": "What the bank or Stripe said, for people; null when reason is.",
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "object": {
                        "description": "Always auto_topup_charge.",
                        "enum": [
                          "auto_topup_charge"
                        ],
                        "type": "string"
                      },
                      "pack": {
                        "description": "The credit pack (catalog pack ID).",
                        "type": "string"
                      },
                      "reason": {
                        "description": "Why it failed (the off_reason it set) or was skipped (monthly_cap, trust_limit: it would have passed rolling_limit_cents); null otherwise.",
                        "enum": [
                          "card_declined",
                          "authentication_required",
                          "no_card",
                          "billing_address_required",
                          "payment_failed",
                          "disputed",
                          "monthly_cap",
                          "trust_limit"
                        ],
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "status": {
                        "description": "processing (the charge is under way), succeeded (paid: its credits were added, once), failed (nothing charged: auto top-up turned off, see reason) or skipped (it would have passed the monthly cap or the 7-day limit: nothing charged, auto top-up stays on).",
                        "enum": [
                          "processing",
                          "succeeded",
                          "failed",
                          "skipped"
                        ],
                        "type": "string"
                      }
                    },
                    "required": [
                      "object",
                      "id",
                      "status",
                      "pack",
                      "credits",
                      "amount_total",
                      "amount_tax",
                      "currency",
                      "reason",
                      "message",
                      "created_at"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "auto_topup.skipped"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "auto_topup.skipped",
        "tags": [
          "Events"
        ]
      }
    },
    "auto_topup.succeeded": {
      "post": {
        "description": "Auto top-up bought its pack: the charge was paid and the pack's credits added (once). The body is the event object (its data a AutoTopupCharge); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.auto_topup_succeeded",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "amount_tax": {
                        "description": "The tax in amount_total (Stripe Tax: only where SocialTap collects it); null when amount_total is.",
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "amount_total": {
                        "description": "Charged, tax included, in cents of currency; null when nothing was charged or before it is known.",
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "created_at": {
                        "description": "When the balance crossed the threshold, RFC 3339 UTC.",
                        "format": "date-time",
                        "type": "string"
                      },
                      "credits": {
                        "description": "Credits the pack adds.",
                        "type": "integer"
                      },
                      "currency": {
                        "description": "amount_total's currency (ISO 4217).",
                        "enum": [
                          "usd"
                        ],
                        "type": "string"
                      },
                      "id": {
                        "description": "Top-up ID (atu_…): the ref of its credit_transaction, and on the Stripe payment's metadata.",
                        "type": "string"
                      },
                      "message": {
                        "description": "What the bank or Stripe said, for people; null when reason is.",
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "object": {
                        "description": "Always auto_topup_charge.",
                        "enum": [
                          "auto_topup_charge"
                        ],
                        "type": "string"
                      },
                      "pack": {
                        "description": "The credit pack (catalog pack ID).",
                        "type": "string"
                      },
                      "reason": {
                        "description": "Why it failed (the off_reason it set) or was skipped (monthly_cap, trust_limit: it would have passed rolling_limit_cents); null otherwise.",
                        "enum": [
                          "card_declined",
                          "authentication_required",
                          "no_card",
                          "billing_address_required",
                          "payment_failed",
                          "disputed",
                          "monthly_cap",
                          "trust_limit"
                        ],
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "status": {
                        "description": "processing (the charge is under way), succeeded (paid: its credits were added, once), failed (nothing charged: auto top-up turned off, see reason) or skipped (it would have passed the monthly cap or the 7-day limit: nothing charged, auto top-up stays on).",
                        "enum": [
                          "processing",
                          "succeeded",
                          "failed",
                          "skipped"
                        ],
                        "type": "string"
                      }
                    },
                    "required": [
                      "object",
                      "id",
                      "status",
                      "pack",
                      "credits",
                      "amount_total",
                      "amount_tax",
                      "currency",
                      "reason",
                      "message",
                      "created_at"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "auto_topup.succeeded"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "auto_topup.succeeded",
        "tags": [
          "Events"
        ]
      }
    },
    "credits.depleted": {
      "post": {
        "description": "The balance reached 0 (once, until credits are added). The owner is also emailed, at most once a day, whatever the notification settings say: it is how a leaked key is noticed. The body is the event object (its data a CreditsDepletedData); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.credits_depleted",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "balance": {
                        "description": "The balance: 0.",
                        "type": "integer"
                      }
                    },
                    "required": [
                      "balance"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "credits.depleted"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "credits.depleted",
        "tags": [
          "Events"
        ]
      }
    },
    "credits.low": {
      "post": {
        "description": "A balance change took the balance from above the account's low_balance_threshold to at or below it (once per crossing; the owner is emailed too). The body is the event object (its data a CreditsLowData); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.credits_low",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "balance": {
                        "description": "The balance after the change that crossed the threshold.",
                        "type": "integer"
                      },
                      "low_balance_threshold": {
                        "description": "The account's low_balance_threshold at the time.",
                        "type": "integer"
                      }
                    },
                    "required": [
                      "balance",
                      "low_balance_threshold"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "credits.low"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "credits.low",
        "tags": [
          "Events"
        ]
      }
    },
    "job.canceled": {
      "post": {
        "description": "A canceled job ended: its running items finished. The body is the event object (its data a JobEventData); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.job_canceled",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "created_at": {
                        "format": "date-time",
                        "type": "string"
                      },
                      "credits": {
                        "properties": {
                          "charged": {
                            "description": "Credits charged so far, each page once (items' prices; failed items are free).",
                            "type": "integer"
                          },
                          "max": {
                            "description": "max_credits: the most the job may spend.",
                            "type": "integer"
                          },
                          "reserved": {
                            "description": "Credits its running pages may still use (0 once the job ends).",
                            "type": "integer"
                          }
                        },
                        "required": [
                          "max",
                          "reserved",
                          "charged"
                        ],
                        "type": "object"
                      },
                      "finished_at": {
                        "format": "date-time",
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "id": {
                        "type": "string"
                      },
                      "metadata": {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      "object": {
                        "enum": [
                          "job"
                        ],
                        "type": "string"
                      },
                      "request_counts": {
                        "properties": {
                          "canceled": {
                            "type": "integer"
                          },
                          "expired": {
                            "type": "integer"
                          },
                          "failed": {
                            "type": "integer"
                          },
                          "queued": {
                            "description": "Not started.",
                            "type": "integer"
                          },
                          "running": {
                            "description": "Started (fetching, waiting for a retry or walking pages).",
                            "type": "integer"
                          },
                          "succeeded": {
                            "type": "integer"
                          },
                          "total": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "total",
                          "queued",
                          "running",
                          "succeeded",
                          "failed",
                          "canceled",
                          "expired"
                        ],
                        "type": "object"
                      },
                      "results_url": {
                        "description": "Every result as JSON Lines, the job's signed results_url: it works without the API key for 1 hour after the event; GET url for a fresh one. Reading the event with a key without jobs:read, this is url instead: the link is a job's results, whatever key holds it.",
                        "type": "string"
                      },
                      "status": {
                        "enum": [
                          "queued",
                          "running",
                          "canceling",
                          "completed",
                          "canceled",
                          "expired"
                        ],
                        "type": "string"
                      },
                      "url": {
                        "description": "GET this (with your API key) for the job.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "object",
                      "id",
                      "status",
                      "request_counts",
                      "credits",
                      "metadata",
                      "created_at",
                      "finished_at",
                      "url",
                      "results_url"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "job.canceled"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "job.canceled",
        "tags": [
          "Events"
        ]
      }
    },
    "job.completed": {
      "post": {
        "description": "A job ended with every item ended (check request_counts: items fail individually). The body is the event object (its data a JobEventData); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.job_completed",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "created_at": {
                        "format": "date-time",
                        "type": "string"
                      },
                      "credits": {
                        "properties": {
                          "charged": {
                            "description": "Credits charged so far, each page once (items' prices; failed items are free).",
                            "type": "integer"
                          },
                          "max": {
                            "description": "max_credits: the most the job may spend.",
                            "type": "integer"
                          },
                          "reserved": {
                            "description": "Credits its running pages may still use (0 once the job ends).",
                            "type": "integer"
                          }
                        },
                        "required": [
                          "max",
                          "reserved",
                          "charged"
                        ],
                        "type": "object"
                      },
                      "finished_at": {
                        "format": "date-time",
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "id": {
                        "type": "string"
                      },
                      "metadata": {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      "object": {
                        "enum": [
                          "job"
                        ],
                        "type": "string"
                      },
                      "request_counts": {
                        "properties": {
                          "canceled": {
                            "type": "integer"
                          },
                          "expired": {
                            "type": "integer"
                          },
                          "failed": {
                            "type": "integer"
                          },
                          "queued": {
                            "description": "Not started.",
                            "type": "integer"
                          },
                          "running": {
                            "description": "Started (fetching, waiting for a retry or walking pages).",
                            "type": "integer"
                          },
                          "succeeded": {
                            "type": "integer"
                          },
                          "total": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "total",
                          "queued",
                          "running",
                          "succeeded",
                          "failed",
                          "canceled",
                          "expired"
                        ],
                        "type": "object"
                      },
                      "results_url": {
                        "description": "Every result as JSON Lines, the job's signed results_url: it works without the API key for 1 hour after the event; GET url for a fresh one. Reading the event with a key without jobs:read, this is url instead: the link is a job's results, whatever key holds it.",
                        "type": "string"
                      },
                      "status": {
                        "enum": [
                          "queued",
                          "running",
                          "canceling",
                          "completed",
                          "canceled",
                          "expired"
                        ],
                        "type": "string"
                      },
                      "url": {
                        "description": "GET this (with your API key) for the job.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "object",
                      "id",
                      "status",
                      "request_counts",
                      "credits",
                      "metadata",
                      "created_at",
                      "finished_at",
                      "url",
                      "results_url"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "job.completed"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "job.completed",
        "tags": [
          "Events"
        ]
      }
    },
    "job.expired": {
      "post": {
        "description": "A job reached its deadline; its unfinished items expired. The body is the event object (its data a JobEventData); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.job_expired",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "created_at": {
                        "format": "date-time",
                        "type": "string"
                      },
                      "credits": {
                        "properties": {
                          "charged": {
                            "description": "Credits charged so far, each page once (items' prices; failed items are free).",
                            "type": "integer"
                          },
                          "max": {
                            "description": "max_credits: the most the job may spend.",
                            "type": "integer"
                          },
                          "reserved": {
                            "description": "Credits its running pages may still use (0 once the job ends).",
                            "type": "integer"
                          }
                        },
                        "required": [
                          "max",
                          "reserved",
                          "charged"
                        ],
                        "type": "object"
                      },
                      "finished_at": {
                        "format": "date-time",
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "id": {
                        "type": "string"
                      },
                      "metadata": {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      "object": {
                        "enum": [
                          "job"
                        ],
                        "type": "string"
                      },
                      "request_counts": {
                        "properties": {
                          "canceled": {
                            "type": "integer"
                          },
                          "expired": {
                            "type": "integer"
                          },
                          "failed": {
                            "type": "integer"
                          },
                          "queued": {
                            "description": "Not started.",
                            "type": "integer"
                          },
                          "running": {
                            "description": "Started (fetching, waiting for a retry or walking pages).",
                            "type": "integer"
                          },
                          "succeeded": {
                            "type": "integer"
                          },
                          "total": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "total",
                          "queued",
                          "running",
                          "succeeded",
                          "failed",
                          "canceled",
                          "expired"
                        ],
                        "type": "object"
                      },
                      "results_url": {
                        "description": "Every result as JSON Lines, the job's signed results_url: it works without the API key for 1 hour after the event; GET url for a fresh one. Reading the event with a key without jobs:read, this is url instead: the link is a job's results, whatever key holds it.",
                        "type": "string"
                      },
                      "status": {
                        "enum": [
                          "queued",
                          "running",
                          "canceling",
                          "completed",
                          "canceled",
                          "expired"
                        ],
                        "type": "string"
                      },
                      "url": {
                        "description": "GET this (with your API key) for the job.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "object",
                      "id",
                      "status",
                      "request_counts",
                      "credits",
                      "metadata",
                      "created_at",
                      "finished_at",
                      "url",
                      "results_url"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "job.expired"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "job.expired",
        "tags": [
          "Events"
        ]
      }
    },
    "plan.changed": {
      "post": {
        "description": "An upgrade was paid: the new plan and a new month started now, and its credits were added. The body is the event object (its data a PlanEventData); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.plan_changed",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "credits": {
                        "description": "Credits this event added; 0 when it added none.",
                        "type": "integer"
                      },
                      "current_period_end": {
                        "description": "When the plan renews next, RFC 3339 UTC; null when it has ended.",
                        "format": "date-time",
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "plan": {
                        "description": "The monthly plan (catalog plan ID).",
                        "type": "string"
                      }
                    },
                    "required": [
                      "plan",
                      "credits",
                      "current_period_end"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "plan.changed"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "plan.changed",
        "tags": [
          "Events"
        ]
      }
    },
    "plan.ended": {
      "post": {
        "description": "A monthly plan ended (canceled, or its payment retries failed): the monthly credits left ended with it, pack and top-up credits stay, and the account is pay as you go. The body is the event object (its data a PlanEventData); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.plan_ended",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "credits": {
                        "description": "Credits this event added; 0 when it added none.",
                        "type": "integer"
                      },
                      "current_period_end": {
                        "description": "When the plan renews next, RFC 3339 UTC; null when it has ended.",
                        "format": "date-time",
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "plan": {
                        "description": "The monthly plan (catalog plan ID).",
                        "type": "string"
                      }
                    },
                    "required": [
                      "plan",
                      "credits",
                      "current_period_end"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "plan.ended"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "plan.ended",
        "tags": [
          "Events"
        ]
      }
    },
    "plan.payment_failed": {
      "post": {
        "description": "A monthly plan's renewal payment failed: no new credits were added and the owner was emailed. Stripe retries it; the plan ends if the retries fail. The body is the event object (its data a PlanEventData); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.plan_payment_failed",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "credits": {
                        "description": "Credits this event added; 0 when it added none.",
                        "type": "integer"
                      },
                      "current_period_end": {
                        "description": "When the plan renews next, RFC 3339 UTC; null when it has ended.",
                        "format": "date-time",
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "plan": {
                        "description": "The monthly plan (catalog plan ID).",
                        "type": "string"
                      }
                    },
                    "required": [
                      "plan",
                      "credits",
                      "current_period_end"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "plan.payment_failed"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "plan.payment_failed",
        "tags": [
          "Events"
        ]
      }
    },
    "plan.renewed": {
      "post": {
        "description": "A monthly plan's payment went through: its credits were added and what was left of last month's ended (the first payment of a plan too). The body is the event object (its data a PlanEventData); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.plan_renewed",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "credits": {
                        "description": "Credits this event added; 0 when it added none.",
                        "type": "integer"
                      },
                      "current_period_end": {
                        "description": "When the plan renews next, RFC 3339 UTC; null when it has ended.",
                        "format": "date-time",
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "plan": {
                        "description": "The monthly plan (catalog plan ID).",
                        "type": "string"
                      }
                    },
                    "required": [
                      "plan",
                      "credits",
                      "current_period_end"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "plan.renewed"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "plan.renewed",
        "tags": [
          "Events"
        ]
      }
    },
    "webhook.test": {
      "post": {
        "description": "Sent by POST /v1/webhook_endpoints/{id}/test to that endpoint only. The body is the event object (its data a WebhookTestData); verify webhook-signature before trusting it (Standard Webhooks).",
        "operationId": "webhooks.webhook_test",
        "parameters": [
          {
            "description": "The event ID (evt_…), the same on every retry: deduplicate deliveries on it.",
            "in": "header",
            "name": "webhook-id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "When this attempt was signed, in Unix seconds: reject deliveries outside your tolerance (replays).",
            "in": "header",
            "name": "webhook-timestamp",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Space-separated v1,SIGNATURE entries, each the base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body joined by dots, with one active secret (two during a rotation): accept the delivery when one matches.",
            "in": "header",
            "name": "webhook-signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "data": {
                    "description": "The type's data object (small: a summary plus links).",
                    "properties": {
                      "webhook_endpoint_id": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "webhook_endpoint_id"
                    ],
                    "type": "object"
                  },
                  "id": {
                    "description": "The event ID (evt_…): the webhook-id header of every delivery, the same on retries. Deduplicate on it.",
                    "type": "string"
                  },
                  "object": {
                    "description": "Always event.",
                    "enum": [
                      "event"
                    ],
                    "type": "string"
                  },
                  "timestamp": {
                    "description": "When it happened.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "type": {
                    "description": "The event type (event types table); new types may be added.",
                    "enum": [
                      "webhook.test"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "id",
                  "type",
                  "timestamp",
                  "data"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Any other answer is retried on the schedule; 410 disables the endpoint."
          }
        },
        "summary": "webhook.test",
        "tags": [
          "Events"
        ]
      }
    }
  }
}
